#include "hk_vidicon.h"

#include <fstream>
#include "HCNetSDK.h"
#include "common/snowflake/snowflake.h"
#include "common/utils/base64_util.h"
#include "common/utils/process_util.h"
#include "common/utils/file_util.h"

namespace zsy
{
    HKVidicon::HKVidicon(const VidiconConfig &config)
        : Vidicon(config)
    {
        if (config.has_hksdk_config())
        {
            const auto homeDir = ProcessUtil::homeDir();
            FileUtil::createDir(homeDir + "/" + config.hksdk_config().temp_dir());
            status = Available;
        } else
        {
            status = Unavailable;
            LOGGER_WARN("海康摄像机 {} 不可用，未指定摄像机配置", config.name());
        }
    }

    std::string HKVidicon::photograph()
    {
        LOCK_BIZ(config.sn())
        {
            if (status == Unavailable)
            {
                LOGGER_ERROR("摄像机 {} 不可用", config.name());
                return {};
            }
            try
            {
                LOGGER_INFO("摄像机正在拍照，设备名称：{}", config.name());

                const auto homeDir = ProcessUtil::homeDir();
                BOOL succ = NET_DVR_Init();
                if (!succ)
                {
                    LOGGER_ERROR("摄像机初始化失败：{} {}", NET_DVR_GetLastError(), NET_DVR_GetErrorMsg());
                    NET_DVR_Cleanup();
                    return {};
                }
                auto logPathStr = homeDir + "/" + config.hksdk_config().log_path();

                succ = NET_DVR_SetLogToFile(3, logPathStr.data(), true);
                if (!succ)
                {
                    LOGGER_ERROR("摄像机日志设置失败：{} {}", NET_DVR_GetLastError(), NET_DVR_GetErrorMsg());
                    NET_DVR_Cleanup();
                    return {};
                }
                NET_DVR_DEVICEINFO_V30 DeviceInfoTmp{};

                auto hksdk_config = config.hksdk_config();
                std::string ip = hksdk_config.ip();
                std::string username = hksdk_config.username();
                std::string passwd = hksdk_config.passwd();

                LONG lLoginID = NET_DVR_Login_V30(ip.data(),
                                                  hksdk_config.port(),
                                                  username.data(),
                                                  passwd.data(), &DeviceInfoTmp);

                if (lLoginID == -1)
                {
                    DWORD e = NET_DVR_GetLastError();
                    auto m = NET_DVR_GetErrorMsg();
                    LOGGER_ERROR("摄像机登录失败：{} {}", e, m);
                    NET_DVR_Cleanup();
                    return {};
                }

                NET_DVR_JPEGPARA JpgPara{};
                JpgPara.wPicSize = 0xff;
                JpgPara.wPicQuality = 0;

                auto dir = homeDir + "/" + config.hksdk_config().temp_dir();
                FileUtil::createDir(dir);

                std::string filename = dir + "/car_body_" + Snowflake::genIdStr() + ".jpg";
                if (!NET_DVR_CaptureJPEGPicture(lLoginID, 1, &JpgPara, filename.data()))
                {
                    LOGGER_ERROR("摄像机拍照失败：{} {}", NET_DVR_GetLastError(), NET_DVR_GetErrorMsg());
                    NET_DVR_Cleanup();
                    return {};
                }
                LOGGER_INFO("摄像机拍照完成：{}", filename);

                NET_DVR_Logout_V30(lLoginID);
                NET_DVR_Cleanup();

                auto content = FileUtil::read(filename);
                FileUtil::remove(filename);
                return Base64::encode(content);
            } catch (std::exception &e)
            {
                LOGGER_ERROR("摄像机拍照失败：{}", e.what());
                return {};
            } catch (...)
            {
                LOGGER_ERROR("未知异常，摄像机拍照失败");
                return {};
            }
        }
        else
        {
            LOGGER_ERROR("摄像机：{}，正在拍照，无法使用", config.sn());
            return {};
        }
    }
} // zsy