#ifndef NEBULOSITY_DETECTOR_H
#define NEBULOSITY_DETECTOR_H

#include <opencv2/opencv.hpp>
#include "../buffer/imagebuffer.h"
#include "../io/logger.h"
#include <memory>
#include <vector>

/**
 * @brief The NebulosityDetector class provides functionality to detect extensive nebulosity in astronomical images.
 *
 * This class analyzes images to determine if they contain extensive nebulosity that might be
 * adversely affected by background extraction processes. It uses texture analysis, local contrast
 * variations, and other metrics to calculate a "nebulosity score" for the image.
 */
class NebulosityDetector
{
    public:
        /**
         * @brief Structure to hold detailed nebulosity metrics
         */
        struct NebulosityMetrics
        {
            double meanPixelValue = 0.0;
            double standardDeviation = 0.0;
            double pixelPercentage = 0.0;
            double textureUniformity = 0.0;
            double lowGradientPercentage = 0.0;
            double diffuseFactor = 0.0;
            double spatialUniformityFactor = 0.0;
            double spatialFactor = 0.0;
            double centerPeripheryRatio = 0.0;
            double concentrationFactor = 0.0;
            double enhancedPixelPercentage = 0.0;
            double enhancedTextureUniformity = 0.0;
            double enhancedStddevFactor = 0.0;
            double baseScore = 0.0;
            double pixelBoost = 0.0;
            double textureBoost = 0.0;
            double haBoost = 0.0;
            double extensiveBoost = 0.0;
            float finalScore = 0.0f;
        };
        /**
         * @brief Construct a new NebulosityDetector object with default settings
         */
        NebulosityDetector();

        /**
         * @brief Set the detection threshold
         * @param threshold The threshold value (0.0-1.0, default: 0.6)
         */
        void setDetectionThreshold(float threshold);

        /**
         * @brief Get the current detection threshold
         * @return The current threshold value
         */
        float getDetectionThreshold() const;

        /**
         * @brief Detect if an image contains extensive nebulosity
         * @param image The input image as OpenCV Mat
         * @param nebulosityScore Output parameter that will contain the calculated nebulosity score
         * @return True if extensive nebulosity is detected, false otherwise
         */
        bool detectExtensiveNebulosity(const cv::Mat &image, float &nebulosityScore);

        /**
         * @brief Detect if an image contains extensive nebulosity and store detailed metrics
         * @param image The input image as OpenCV Mat
         * @param metrics Output parameter that will contain all the calculated metrics
         * @return True if extensive nebulosity is detected, false otherwise
         */
        bool detectExtensiveNebulosity(const cv::Mat &image, NebulosityMetrics &metrics);

        /**
         * @brief Detect if an image contains extensive nebulosity
         * @param image The input image as ImageBuffer
         * @param nebulosityScore Output parameter that will contain the calculated nebulosity score
         * @return True if extensive nebulosity is detected, false otherwise
         */
        template <typename T>
        bool detectExtensiveNebulosity(const std::shared_ptr<ImageBuffer<T>> &image, float &nebulosityScore);

        /**
         * @brief Get the last calculated nebulosity metrics
         * @return The nebulosity metrics structure
         */
        const NebulosityMetrics &getLastMetrics() const;

        /**
         * @brief Generate a visualization of the nebulosity detection
         * @param image The input image
         * @param nebulosityScore The calculated nebulosity score
         * @return A visualization image showing the detected nebulosity
         */
        cv::Mat generateVisualization(const cv::Mat &image, float nebulosityScore);

    private:
        /**
         * @brief Convert an ImageBuffer to an OpenCV Mat
         * @param image The input ImageBuffer
         * @return The converted OpenCV Mat
         */
        template <typename T>
        cv::Mat imageBufferToMat(const std::shared_ptr<ImageBuffer<T>> &image);

    private:
        float m_detectionThreshold;
        NebulosityMetrics m_lastMetrics;
};

// Include the template implementation
#include "nebulosity_detector.tpp"

#endif // NEBULOSITY_DETECTOR_H
