#ifndef MYUTILS_H_
#define MYUTILS_H_

#include <mutex>
#include <sstream>
#include <fstream>
#include <dirent.h>
#include <time.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string>
#include <vector>
#include <algorithm>
#include <set>
#include <map>
#include <memory>
#include <cstring>

#include "Log.h"
#include "ErrorCode.h"
#include "MyYaml.h"
#include "json/json.h"
#include "AppCommon.h"

#ifdef ASCEND
#include "acl/acl.h"
#include "acl/ops/acl_dvpp.h"
#endif


namespace ai_matrix
{
    class MyUtils final
    {
    public:
        static MyUtils *getins();

        //计算均值
        float getMean(const std::vector<float> &data);

        //计算最大值
        float getMax(const std::vector<float> &data);

        //计算最小值
        float getMin(const std::vector<float> &data);

        //计算中位数
        float getMedian(const std::vector<float> &data);

        //获取时间戳
        std::string get_timestamp_file();
        std::string get_timestamp_log();
        //获取日期
        std::string get_date();
        //获取时间
        std::string get_time();

        //时间戳转化为时间 毫秒级
        std::string Stamp2Time(long long timestamp, bool has_msec = false);

        //创建文件夹
        std::string create_dir_name(std::string root, std::string name);
        std::string create_dir_date_name_time(std::string root, std::string name);
        std::string create_dir_date(std::string root);

        //创建文件路径
        std::string create_file_path(std::string root, std::string name, std::string suffix);

        //字符串分割函数
        std::vector<std::string> split(std::string str, std::string pattern);

        //float 转 string
        std::string getStringFromFloat(float f);

        //bool 转 string
        std::string getStringFromBool(bool b);

        /**
        * 拷贝文件
        * @param filePath 源文件位置
        * @param savePath 将要拷贝的新位置
        * @return
        */
        bool copyFile(std::string filePath, std::string savePath);

        //替换string中所有指定字符串
        std::string& replace_all_distinct(std::string &str, const std::string &old_value, const std::string &new_value);

        //获取北京当前日期
        std::string GetDate();
        //获取北京当前时间
        std::string GetTime();
        //获取当前时间距1970年的毫秒数
        uint64_t GetCurrentTimeMillis();

        //获取指定时间距1970年的毫秒数 (入参格式：YYYY-MM-DD hh-mm-ss)
        uint64_t GetParamTimeMilliSeconds(std::string &strDateTime);

        std::vector<float> SplitAnchor(std::string &strLine, const std::set<char> &setDelimiters);

        //创建文件夹路径
        bool CreateDirPath(std::string strDirPath);

#ifdef ASCEND
        //拷贝Device数据到Host
        bool MemcpyDeviceToHost(std::shared_ptr<void> *pHostData, const void *pDeviceBuffer, uint32_t iBufferSize);

        //拷贝Host数据到Device
        bool MemcpyHostToDevice(std::shared_ptr<void> *pDeviceData, const void *pHostBuffer, uint32_t iBufferSize, bool bDvppFlag = true);
#endif

        //获取指定毫秒数的对应的日期时间
        std::string GetDateTimeByMilliSeconds(uint64_t i64MilliSeconds, bool bFormatFlag = false);

        //校验是否识别该目标
        bool ChkIsHaveTarget(const std::string &strOneTarget);

        //读取json格式文件内容
        bool ReadJsonInfo(Json::Value &jvFileInfo, std::string &strFilePath, int iRetry = 3);

        //json格式内容写入文件
        bool WriteJsonInfo(Json::Value &jvFileInfo, std::string &strFilePath);

        //获取第1步得分最高框
        void GetMaxScoreResult(std::vector<stDetection> &vecResult);

        //获取第二步缩放比例
        float GetStep2ResizeRatio(Step1Location &step1Location, int iModelWidth, int iModelHeight);

        //第二步坐标还原
        void Step2ResetLocation(SingleData &singleData, float fResizeRatio,
                                std::shared_ptr<ProcessData> pProcessData, Step1Location &step1Location);

    private:
        MyUtils() = default;
        MyUtils(const MyUtils &) = delete;
        MyUtils(MyUtils &&) = delete;
        MyUtils &operator=(const MyUtils &) = delete;
        MyUtils &operator=(MyUtils &&) = delete;
        ~MyUtils() = default;

        //定义一个嵌套类，负责释放内存，操作系统自动完成，不用担心内存泄露
        class GarbageCollector
        {
        public:
            ~GarbageCollector()
            {
                if (MyUtils::ins)
                {
                    delete MyUtils::ins;
                    MyUtils::ins = nullptr;
                }
            }
        };

        static GarbageCollector gc;
        static MyUtils *ins;
        static std::mutex mx; //锁，保证线程安全
    };
}

#endif