#ifndef LIVESTACKER_H
#define LIVESTACKER_H

#include <string>
#include <vector>
#include <memory>
#include "buffer/imagebuffer.h"

/**
 * @brief The LiveStacker class is the main class for the livestacker application.
 *
 * It provides functionality for stacking astronomical images to produce a clearer result.
 * The class operates in stateful mode, processing one frame at a time and maintaining state between runs.
 */
class LiveStacker
{
    public:
        /**
         * @brief Enum for the stacking method
         */
        enum class StackingMethod
        {
            Mean,       ///< Average stacking
            Median,     ///< Median stacking
            SigmaClip   ///< Sigma clipping stacking
        };

        /**
         * @brief Construct a new LiveStacker object
         */
        LiveStacker();

        /**
         * @brief Destroy the LiveStacker object
         */
        ~LiveStacker();

        /**
         * @brief Set the stacking method
         * @param method The stacking method to use
         */
        void setStackingMethod(StackingMethod method);

        /**
         * @brief Process a single frame and update the internal state
         * @param filename The filename of the frame to process
         * @param outputFilename The filename to save the result to
         * @return True if successful, false otherwise
         */
        bool processFrame(const std::string &filename, const std::string &outputFilename);

        /**
         * @brief Save the current state to a file
         * @param stateFilename The filename to save the state to
         * @return True if successful, false otherwise
         */
        bool saveState(const std::string &stateFilename);

        /**
         * @brief Load the state from a file
         * @param stateFilename The filename to load the state from
         * @return True if successful, false otherwise
         */
        bool loadState(const std::string &stateFilename);

        /**
         * @brief Reset the internal state
         */
        void reset();

        /**
         * @brief Set whether to apply dark frame subtraction
         * @param apply Whether to apply dark frame subtraction
         */
        void setApplyDarkSubtraction(bool apply);

        /**
         * @brief Set the dark frame
         * @param filename The filename of the dark frame
         * @return True if successful, false otherwise
         */
        bool setDarkFrame(const std::string &filename);

        /**
         * @brief Set whether to align frames
         * @param align Whether to align frames
         */
        void setAlignFrames(bool align);

        /**
         * @brief Set the background adjustment percentage
         * @param percentage The background adjustment percentage (0-100)
         */
        void setBackgroundAdjustment(float percentage);

        /**
         * @brief Set the contrast adjustment percentage
         * @param percentage The contrast adjustment percentage (0-200)
         */
        void setContrastAdjustment(float percentage);

        /**
         * @brief Set the saturation adjustment percentage
         * @param percentage The saturation adjustment percentage (0-100)
         */
        void setSaturationAdjustment(float percentage);

        /**
         * @brief Set the compression percentage
         * @param percentage The compression percentage (0-100)
         */
        void setCompressionPercentage(float percentage);

        /**
         * @brief Set the median filter size
         * @param size The median filter size (0 to disable)
         */
        void setMedianFilterSize(int size);

        /**
         * @brief Set the local histogram equalization parameters
         * @param enable Whether to enable local histogram equalization
         * @param windowSize The size of the local window (default: 31)
         * @param clipLimit The contrast limit to prevent over-amplification of noise (0.0-4.0, default: 2.0)
         */
        void setLocalHistogramEqualization(bool enable, int windowSize = 31, float clipLimit = 2.0f);

        /**
         * @brief Set the denoising parameters
         * @param method The denoising method to use (0=None, 1=NonLocalMeans, 2=Bilateral)
         * @param strength The strength of the denoising effect (1-30, default: 10)
         */
        void setDenoising(int method, int strength = 10);

        /**
         * @brief Set the maximum number of stars to use for alignment
         * @param maxStars The maximum number of stars
         */
        void setMaxAlignmentStars(int maxStars);

        /**
         * @brief Set the sigma clipping parameters
         * @param frames The number of frames to use for sigma clipping
         * @param lower The lower bound for sigma clipping
         * @param upper The upper bound for sigma clipping
         */
        void setSigmaClippingParams(int frames, float lower, float upper);

        /**
         * @brief Enable diagnostic mode to save intermediate results
         * @param enable Whether to enable diagnostic mode
         * @param outputPrefix The prefix for output files
         */
        void setDiagnosticMode(bool enable, const std::string &outputPrefix = "frame_");

        /**
         * @brief Set the frame quality threshold
         * @param threshold The threshold for frame quality (0.0-1.0)
         */
        void setQualityThreshold(float threshold);

        /**
         * @brief Set the polynomial degree for background modeling
         * @param degree The polynomial degree (1-4, default: 2)
         */
        void setBackgroundPolynomialDegree(int degree);

        /**
         * @brief Set the sample grid size for background extraction
         * @param gridSize The grid size (8-64, default: 16)
         */
        void setBackgroundSampleGridSize(int gridSize);

        /**
         * @brief Set the protection threshold for nebulae and faint objects
         * @param threshold The protection threshold (0.0-1.0, default: 0.5)
         */
        void setBackgroundProtectionThreshold(float threshold);

        /**
         * @brief Set the smoothness factor for the background model
         * @param smoothness The smoothness factor (0.0-1.0, default: 0.5)
         */
        void setBackgroundSmoothnessFactor(float smoothness);

        /**
         * @brief Enable benchmark mode to time operations
         * @param enable Whether to enable benchmark mode
         */
        void setBenchmarkMode(bool enable);

        /**
         * @brief Get the last error message
         * @return The last error message
         */
        std::string getLastError() const;

    private:
        // Private helper methods
        std::shared_ptr<ImageBuffer8bit> applyDarkSubtraction(const std::shared_ptr<ImageBuffer8bit> &frame);
        std::shared_ptr<ImageBuffer8bit> alignFrame(const std::shared_ptr<ImageBuffer8bit> &frame);
        void updateMeanStack(const std::shared_ptr<ImageBuffer8bit> &newFrame);
        void reprocessStack();
        std::shared_ptr<ImageBuffer8bit> applyPostProcessing(const std::shared_ptr<ImageBuffer8bit> &frame);

        class Impl;
        std::unique_ptr<Impl> m_impl;
};

#endif // LIVESTACKER_H
