#pragma once

#include <string>
#include <opencv2/opencv.hpp> // all opencv header
#include "hdrplus/burst.h"
#include "hdrplus/align.h"
#include "hdrplus/merge.h"
#include "hdrplus/finish.h"

namespace hdrplus
{

    inline cv::Mat convert16bit2_8bit_(cv::Mat ans) {
        if(ans.type()==CV_16UC3){
            cv::MatIterator_<cv::Vec3w> it, end;
            for( it = ans.begin<cv::Vec3w>(), end = ans.end<cv::Vec3w>(); it != end; ++it)
            {
                // std::cout<<sizeof (*it)[0] <<std::endl;
                (*it)[0] *=(255.0/USHRT_MAX);
                (*it)[1] *=(255.0/USHRT_MAX);
                (*it)[2] *=(255.0/USHRT_MAX);
            }
            ans.convertTo(ans, CV_8UC3);
        }else if(ans.type()==CV_16UC1){
            u_int16_t* ptr = (u_int16_t*)ans.data;
            int end = ans.rows*ans.cols;
            for(int i=0;i<end;i++){
                *(ptr+i) *=(255.0/USHRT_MAX);
            }
            ans.convertTo(ans, CV_8UC1);
        }else{
            // std::cout<<"Unsupported Data Type"<<std::endl;
        }
        return ans;
    }

    class hdrplus_pipeline
{
    private:
        hdrplus::align align_module;
        hdrplus::merge merge_module;
        hdrplus::finish finish_module;
    
    public:
        void run_pipeline( const std::string& burst_path, const std::string& reference_image_path  );
        bool run_pipeline( const std::vector<std::string>& burst_paths, int reference_image_index, cv::Mat& finalImg  );
        bool run_pipeline( const std::vector<std::vector<uint8_t> >& burst_contents, int reference_image_index, cv::Mat& finalImg  );
        bool run_pipeline( const std::vector<std::shared_ptr<MemFile> >& burst_contents, int reference_image_index, cv::Mat& finalImg  );

        hdrplus_pipeline() = default;
        ~hdrplus_pipeline() = default;
};

} // namespace hdrplus
