/*
 * @Description: 
 * @Version: 1.0
 * @Autor: lishengyin
 * @Date: 2022-03-09 10:55:43
 * @LastEditors: lishengyin
 * @LastEditTime: 2022-09-19 13:57:01
 */
#ifndef __INFINEFILTER_H_
#define __INFINEFILTER_H_

#include <iostream>
#include "Notices.h"
#include "Util/util.h"
#include "Util/logger.h"
#include "Network/Socket.h"
#include "Util/TimeTicker.h"
#include "Util/NoticeCenter.h"
#include "Poller/Timer.h"
#include "CNStreamInferData.h"
#include "config.hpp"
#include <cmath>
#include <queue>

using namespace std;
using namespace toolkit;

namespace gsd
{
    // 推理过滤器
    class InfineFilter
    {
    private:
        struct HistoryData
        {
            std::shared_ptr<Ticker> ticker = nullptr;
            std::shared_ptr<CNStreamInferData> CnStreamInferData = nullptr;
        };

        // 相似数据
        struct SimilarityData
        {
            std::shared_ptr<Ticker> ticker = nullptr;
            InferInfo info;
        };
        
        
    private:
        InfineFilter(){
        }

        InfineFilter(InfineFilter&) = delete;

        InfineFilter& operator=(const InfineFilter&) = delete;

        // 灵敏度  0,1,2,3 
        // 0 - 不过滤
        // 1 - 参考上一个坐标、大小、数量, 如果类似则过滤
        // 2 - 在1的基础上加入 时间间隔,如每2秒取一次结果
        // 3 - 记录每一个结果,并设置超时机制,未超时时:判断当前推理结果与过去的坐标、大小、数量是否类似,类似则过滤
        //     超时时:舍弃历史记录
        int sensitivity = 2; // 灵敏度 

        // 0 - 不过滤
        // 1 - 参考上一个坐标、大小、数量, 如果类似则过滤
        // 2 - 在1的基础上加入 时间间隔,如每2秒取一次结果
        // 3 - 记录每一个结果,并设置超时机制,未超时时:判断当前推理结果与过去的坐标、大小、数量是否类似,类似则过滤
        //     超时时:舍弃历史记录
        int filterLevel = 2; // 过滤器等级

        int interval = 2000; // 时间间隔

        vector<HistoryData> HistoryDatas;

        queue<HistoryData> LatestDatas;

        vector<SimilarityData> SimilarityDatas;

        int TimeOut = 10 * 60 * 1000;
        
        Timer::Ptr timer = nullptr;

    private:
        /**
         * @description: 跟上一次的判断结果
         * @param {*}
         * @return {*}
         */    
        int8_t LastOneJudgment(std::shared_ptr<CNStreamInferData>& cnStreamInferData);

        /**
         * @description:时间间隔
         * @param {*}
         * @return {*}
         */    
        int8_t IntervalJudgment();

        /**
         * @description: 历史判定
         * @param {*}
         * @return {*}
         */    
        int8_t HistoricalJudgment(std::shared_ptr<CNStreamInferData>& cnStreamInferData);

        /**
         * @description: 相似度对比
         * @return {*}
         */        
        int8_t SimilarityJudgment(std::shared_ptr<CNStreamInferData>& cnStreamInferData);

        /**
         * @description: 历史数据检查
         * @param {*}
         * @return {*}
         */    
        void HistoricalCheck();

        /**
         * @description: 时间对比
         * @return {*}
         */        
        void SimilarityCheck();

    public:
        using Ptr = std::shared_ptr<InfineFilter>;

        ~InfineFilter(){}

        /**
         * @description: 小目标过滤器
         * @return {*}
         */    
        int8_t MinBBoxFilter(std::shared_ptr<CNStreamInferData>& cnStreamInferData);

        /**
         * @description: 判定结果
         * @param {*}
         * @return {*}
         */
        int8_t judgementResult(std::shared_ptr<CNStreamInferData>& cnStreamInferData);

        /**
         * @description: 判定是否相识
         * @param {InferInfo&} infer1
         * @param {InferInfo&} infer2
         * @return {*}
         */    
        int8_t CalculateSimilarity(InferInfo& infer1, InferInfo& infer2, std::shared_ptr<CNStreamInferData>& cnStreamInferData);

        /**
         * @description: 相似库对比
         * @return {*}
         */        
        int8_t SimilarityResult(std::shared_ptr<CNStreamInferData>& cnStreamInferData);

        /**
         * @description: 获取ptr
         * @param {*}
         * @return {*}
         */    
        static std::shared_ptr<InfineFilter> getPtr();

        /**
         * @description: 设置等级
         * @param {int} FilterLevel
         * @return {*}
         */    
        int8_t setFilterLevel(int FilterLevel);

        /**
         * @description: 设置时间间隔
         * @param {int} Interval
         * @return {*}
         */    
        int8_t setInterval(int Interval);

        /**
         * @description: 设置超时时间
         * @param {int} timeOut
         * @return {*}
         */    
        int8_t setTimeOut(int timeOut);

        /**
         * @description: getIou
         * @return {*}
         */    
        float getIou(InferInfo infer1, InferInfo infer2, std::shared_ptr<CNStreamInferData>& cnStreamInferData);

    public:
        double bboxSize = 0.0;
    };
} // namespace gsd


#endif