#ifndef ANSSAM_H
#define ANSSAM_H
#pragma once
#include "ANSEngineCommon.h"
#include <string>
#include <opencv2/opencv.hpp>
#include <openvino/openvino.hpp>
#include <array>

namespace ANSCENTER
{
    class ANSENGINE_API ANSSAM: public ANSODBase
    {
    protected:
        std::string     _modelFilePath;
    public:
        virtual bool Initialize(std::string licenseKey, ModelConfig modelConfig, const std::string& modelZipFilePath, const std::string& modelZipPassword, std::string& labelMap) override;
        virtual bool LoadModel(const std::string& modelZipFilePath, const std::string& modelZipPassword) override;
		virtual bool LoadModelFromFolder(std::string licenseKey, ModelConfig modelConfig, std::string modelName, std::string className, const std::string& modelFolder, std::string& labelMap)override;
        virtual bool OptimizeModel(bool fp16, std::string& optimizedModelFolder);
        std::vector<Object> RunInference(const cv::Mat& input);
        std::vector<Object> RunInference(const cv::Mat& input, const std::string& camera_id); 
        bool Destroy();
        ~ANSSAM();
    private:
        bool Init(const std::string& xml_path, float conf, float iou, bool useGpu);
        void Infer(const std::string& image_path);
        cv::Mat Infer(const cv::Mat& image);
        std::vector<cv::Mat> Postprocess(const cv::Mat& oriImage);
        cv::Mat BuildOutput0();
        cv::Mat BuildOutput1();
        void ScaleBoxes(cv::Mat& box, const cv::Size& oriSize);
        std::vector<cv::Mat> ProcessMaskNative(const cv::Mat& oriImage, cv::Mat& protos, cv::Mat& masks_in, cv::Mat& bboxes, cv::Size shape);
        std::vector<cv::Mat> NMS(cv::Mat& prediction, int max_det = 300);
        void xywh2xyxy(cv::Mat& box);
        ov::Tensor Preprocess(cv::Mat& image);
        bool ConvertSize(cv::Mat& image);
        bool ConvertLayout(cv::Mat& image);
        ov::Tensor BuildTensor();
        bool ParseArgs();
        bool BuildProcessor();
        bool IsGpuAvaliable(const ov::Core& core);
        cv::Scalar RandomColor();
        cv::Mat ConvertToBinary(cv::Mat src);
        std::string MaskToPolygons(const cv::Mat& image, cv::Rect& boundingBox, std::vector<cv::Point2f>& polygon);
        cv::Mat Render(const cv::Mat& image, const std::vector<cv::Mat>& vremat);
    private:
        std::shared_ptr<ov::Model> m_model;
        ov::CompiledModel m_compiled_model;
        ov::Core m_core;
        ov::InferRequest m_request;
        std::shared_ptr<ov::preprocess::PrePostProcessor> m_ppp;
        float m_conf;
        float m_iou;
        std::vector<float> input_data;
        int input_width = 0;             
        int input_height = 0;           
        int input_channel = 3;
        ov::Shape model_input_shape;    
        ov::Shape model_output0_shape;  
        ov::Shape model_output1_shape;  
        float ratio = 1.0f;    
        float dw = 0.f;         
        float dh = 0.f;
        int mw = 160;           
        int mh = 160;           
        cv::Mat m_image;
    };
}

#endif
