#include "ApiEngine.h"
#include "AppCommon.h"
using namespace ai_matrix;



ApiEngine::ApiEngine() {}

ApiEngine::~ApiEngine() {}

APP_ERROR ApiEngine::Init()
{
    strPort0_ = engineName_ + "_" + std::to_string(engineId_) + "_0";
    strPort1_ = engineName_ + "_" + std::to_string(engineId_) + "_1";

    LogInfo << "engineId_:" << engineId_ << " ApiEngine Init ok";
    return APP_ERR_OK;
}

APP_ERROR ApiEngine::DeInit()
{
    LogInfo << "ApiEngine engineId_:" << engineId_ << " DeInit ok";
    return APP_ERR_OK;
}

APP_ERROR ApiEngine::Process()
{
    int iRet = APP_ERR_OK;

    httplib::Server svr;

    svr.set_read_timeout(3, 0); // 5 seconds
    svr.set_write_timeout(3, 0); // 5 seconds

    svr.set_error_handler([](const httplib::Request& req, httplib::Response& res) {
        auto fmt = "Error Status: %d";
        char buf[BUFSIZ];
        snprintf(buf, sizeof(buf), fmt, res.status);
        res.set_content(buf, "text/html");
    });

    svr.set_exception_handler([](const httplib::Request& req, httplib::Response& res, std::exception_ptr ep) {
        auto fmt = "<h1>Error 500</h1><p>%s</p>";
        char buf[BUFSIZ];
        try {
            std::rethrow_exception(ep);
        } catch (std::exception &e) {
            snprintf(buf, sizeof(buf), fmt, e.what());
        } catch (...) { // See the following NOTE
            snprintf(buf, sizeof(buf), fmt, "Unknown Exception");
        }
        res.set_content(buf, "text/html");
        res.status = httplib::StatusCode::InternalServerError_500;
    });

//    svr.set_logger([](const httplib::Request& req, const httplib::Response& res){
//        LogInfo << "请求信息：" << req.body;
//        LogInfo << "返回信息：" << res.body;
//    });

//    if (!svr.set_mount_point("/public", Config::getins()->getBaseConfig().strResultPath))
//    {
//        LogError << "创建识别结果文件服务失败,请检查目录是否存在：" << Config::getins()->getBaseConfig().strResultPath;
//    }
//    if (!svr.set_mount_point("/logs", Config::getins()->getBaseConfig().strLogPath))
//    {
//        LogError << "创建日志文件服务失败,请检查目录是否存在：" << Config::getins()->getBaseConfig().strLogPath;
//    }

    svr.Get("/hello", [](const httplib::Request& req, httplib::Response& res){
        res.set_content("Hello, World!", "text/plain");
    });

    svr.Get("/stop_api", [&](const httplib::Request& req, httplib::Response& res){
        svr.stop();
        res.set_content("stop success", "text/plain");
        exit(1);
    });

    svr.Get("/queryBaseSetting", [=](const httplib::Request& req, httplib::Response& res){

        Json::Value response = this->queryBaseSetting();
        res.set_content(response.toStyledString(), "application/json");
    });

    svr.Post("/updateBaseSetting", [=](const httplib::Request& req, httplib::Response& res){

        Json::Value response = this->updateBaseSetting(req.body);
        res.set_content(response.toStyledString(), "application/json");
    });

    svr.Get("/queryLogSetting", [=](const httplib::Request& req, httplib::Response& res){

        Json::Value response = this->queryLogSetting();
        res.set_content(response.toStyledString(), "application/json");
    });

    svr.Post("/updateLogSetting", [=](const httplib::Request& req, httplib::Response& res){

        Json::Value response = this->updateLogSetting(req.body);
        res.set_content(response.toStyledString(), "application/json");
    });

    svr.Get("/queryDataSource", [=](const httplib::Request& req, httplib::Response& res){

        Json::Value response = this->queryDataSource();
        res.set_content(response.toStyledString(), "application/json");
    });

    svr.Post("/updateDataSource", [=](const httplib::Request& req, httplib::Response& res){

        Json::Value response = this->updateDataSource(req.body);
        res.set_content(response.toStyledString(), "application/json");
    });

    svr.Get("/queryIdentifySetting", [=](const httplib::Request& req, httplib::Response& res){

        Json::Value response = this->queryIdentifySetting();
        res.set_content(response.toStyledString(), "application/json");
    });

    svr.Post("/updateIdentifySetting", [=](const httplib::Request& req, httplib::Response& res){

        Json::Value response = this->updateIdentifySetting(req.body);
        res.set_content(response.toStyledString(), "application/json");
    });

    svr.Get("/queryHttpSetting", [=](const httplib::Request& req, httplib::Response& res){

        Json::Value response = this->queryHttpSetting();
        res.set_content(response.toStyledString(), "application/json");
    });

    svr.Post("/updateHttpSetting", [=](const httplib::Request& req, httplib::Response& res){

        Json::Value response = this->updateHttpSetting(req.body);
        res.set_content(response.toStyledString(), "application/json");
    });

    svr.Get("/queryMinioSetting", [=](const httplib::Request& req, httplib::Response& res){

        Json::Value response = this->queryHttpSetting();
        res.set_content(response.toStyledString(), "application/json");
    });

    svr.Post("/updateMinioSetting", [=](const httplib::Request& req, httplib::Response& res){

        Json::Value response = this->updateHttpSetting(req.body);
        res.set_content(response.toStyledString(), "application/json");
    });

    svr.Get("/identify_start", [=](const httplib::Request& req, httplib::Response& res){

        Json::Value response = this->identifyStart();
        res.set_content(response.toStyledString(), "application/json");
    });

    svr.Get("/identify_stop", [=](const httplib::Request& req, httplib::Response& res){

        Json::Value response = this->identifyStop();
        res.set_content(response.toStyledString(), "application/json");
    });

    int port = Config::getins()->getBaseConfig().iApiPort;

    LogInfo << "开启API服务，端口:" << port;
    if (!svr.listen("0.0.0.0", port, 1))
    {
        LogError << "监听端口 " << port << " 失败！API接口无法使用！";
    }

    return APP_ERR_OK;
}

/**
 * 查看基础配置参数
 * @return
 */
Json::Value ApiEngine::queryBaseSetting()
{
    Json::Value response;
    response["success"] = false;
    try {
        BaseConfig baseConfig = Config::getins()->getBaseConfig();
        Json::Value data;
        data["track_name"] = baseConfig.strTrackName;
        data["result_save_days"] = baseConfig.iResultSaveDays;

        response["success"] = true;
        response["msg"] = "";
        response["data"] = data;
    }
    catch (std::exception &e)
    {
        response["msg"] = "接口调用失败！ \n异常内容:" + std::string(e.what());
    }
    return response;
}

/**
 * 修改基础配置参数
 * @param req
 * @return
 */
Json::Value ApiEngine::updateBaseSetting(const std::string &req)
{
    Json::Value response;
    response["success"] = false;
    try {
        Json::CharReaderBuilder readerBuilder;
        std::istringstream iss(req);
        Json::Value root;
        std::string errs;
        bool parsingSuccessful = Json::parseFromStream(readerBuilder, iss, &root, &errs);
        if (!parsingSuccessful)
        {
            response["msg"] = "接口调用参数异常，所传数据非json：" + req;
            return response;
        }

        if (root["track_name"].isString() && root["track_name"].asString() != Config::getins()->config_["base"]["track_name"].as<std::string>())
        {
            Config::getins()->config_["base"]["track_name"] = root["track_name"].asString();
        }
        if (root["result_save_days"].isInt())
        {
            Config::getins()->config_["base"]["result_save_days"] = root["result_save_days"].asInt();
        }
        Config::getins()->writeYaml();

        response["success"] = true;
        response["msg"] = "";
        response["data"] = {};
    }
    catch (std::exception &e)
    {
        response["msg"] = "接口调用失败！请求参数：" + req + "。 \n异常内容:" + std::string(e.what());
    }
    return response;
}

/**
 * 查看日志配置参数
 * @return
 */
Json::Value ApiEngine::queryLogSetting()
{
    Json::Value response;
    response["success"] = false;
    try {
        LogConfig config = Config::getins()->getLogConfig();
        Json::Value data;
        data["out_level"] = config.strOutLevel;
        data["save_level"] = config.strSaveLevel;

        response["success"] = true;
        response["msg"] = "";
        response["data"] = data;
    }
    catch (std::exception &e)
    {
        response["msg"] = "接口调用失败！ \n异常内容:" + std::string(e.what());
    }
    return response;
}

/**
 * 修改日志配置参数
 * @param req
 * @return
 */
Json::Value ApiEngine::updateLogSetting(const std::string &req)
{
    Json::Value response;
    response["success"] = false;
    try {
        Json::CharReaderBuilder readerBuilder;
        std::istringstream iss(req);
        Json::Value root;
        std::string errs;
        bool parsingSuccessful = Json::parseFromStream(readerBuilder, iss, &root, &errs);
        if (!parsingSuccessful)
        {
            response["msg"] = "接口调用参数异常，所传数据非json：" + req;
            return response;
        }

        if (root["out_level"].isString() && root["out_level"].asString() != Config::getins()->config_["log"]["out_level"].as<std::string>())
        {
            Config::getins()->config_["log"]["out_level"] = root["out_level"].asString();
        }
        if (root["save_level"].isString() && root["save_level"].asString() != Config::getins()->config_["log"]["save_level"].as<std::string>())
        {
            Config::getins()->config_["log"]["save_level"] = root["save_level"].asString();
        }

        Config::getins()->writeYaml();

        response["success"] = true;
        response["msg"] = "";
        response["data"] = {};
    }
    catch (std::exception &e)
    {
        response["msg"] = "接口调用失败！请求参数：" + req + "。 \n异常内容:" + std::string(e.what());
    }
    return response;
}

/**
 * 查看当前使用的数据源
 * @return
 */
Json::Value ApiEngine::queryDataSource()
{
    Json::Value response;
    response["success"] = false;
    try {
        std::vector<DataSourceConfig> vecDataSourceConfig = Config::getins()->getAllDataSourceConfig();
        Json::Value data;
        Json::Value sub;
        for (auto &it : vecDataSourceConfig)
        {
            data["url"] = it.strUrl;
            data["skip_interval"] = it.iSkipInterval;
        }
        data["dataSource"] = sub;

        response["success"] = true;
        response["msg"] = "";
        response["data"] = data;
    }
    catch (std::exception &e)
    {
        response["msg"] = "接口调用失败！ \n异常内容:" + std::string(e.what());
    }
    return response;
}

/**
 * 修改数据源
 * @param req
 * @return
 */
Json::Value ApiEngine::updateDataSource(const std::string &req)
{
    Json::Value response;
    response["success"] = false;
    try {
        Json::CharReaderBuilder readerBuilder;
        std::istringstream iss(req);
        Json::Value root;
        std::string errs;
        bool parsingSuccessful = Json::parseFromStream(readerBuilder, iss, &root, &errs);
        if (!parsingSuccessful)
        {
            response["msg"] = "接口调用参数异常，所传数据非json：" + req;
            return response;
        }

        if (root["url"].isString() && root["url"].asString() != Config::getins()->config_["data_source"]["url"].as<std::string>())
        {
            Config::getins()->config_["data_source"]["url"] = root["url"].asString();
        }
        if (root["skip_interval"].isInt())
        {
            Config::getins()->config_["data_source"]["skip_interval"] = root["skip_interval"].asInt();
        }
        if (root["direction"].isInt())
        {
            Config::getins()->config_["data_source"]["direction"] = root["direction"].asInt();
        }
        if (root["left_first"].isInt())
        {
            Config::getins()->config_["data_source"]["left_first"] = root["left_first"].asInt();
        }
        if (root["right_first"].isInt())
        {
            Config::getins()->config_["data_source"]["right_first"] = root["right_first"].asInt();
        }
        Config::getins()->writeYaml();

        response["success"] = true;
        response["msg"] = "";
        response["data"] = {};
    }
    catch (std::exception &e)
    {
        response["msg"] = "接口调用失败！请求参数：" + req + "。 \n异常内容:" + std::string(e.what());
    }
    return response;
}

/**
 * 查看识别配置参数
 * @return
 */
Json::Value ApiEngine::queryIdentifySetting()
{
    Json::Value response;
    response["success"] = false;
    try {
        IdentifyConfig config = Config::getins()->getIdentifyConfig();
        Json::Value data;
        data["side_x_split_span_px"] = config.iSide_X_SplitSpanPx;
        data["top_y_split_span_px"] = config.iTop_Y_SplitSpanPx;

        response["success"] = true;
        response["msg"] = "";
        response["data"] = data;
    }
    catch (std::exception &e)
    {
        response["msg"] = "接口调用失败！ \n异常内容:" + std::string(e.what());
    }
    return response;
}

/**
 * 修改识别配置参数
 * @param req
 * @return
 */
Json::Value ApiEngine::updateIdentifySetting(const std::string &req)
{
    Json::Value response;
    response["success"] = false;
    try {
        Json::CharReaderBuilder readerBuilder;
        std::istringstream iss(req);
        Json::Value root;
        std::string errs;
        bool parsingSuccessful = Json::parseFromStream(readerBuilder, iss, &root, &errs);
        if (!parsingSuccessful)
        {
            response["msg"] = "接口调用参数异常，所传数据非json：" + req;
            return response;
        }

        if (root["top_y_split_span_px"].isString() && root["top_y_split_span_px"].asString() != Config::getins()->config_["identify"]["top_y_split_span_px"].as<std::string>())
        {
            Config::getins()->config_["identify"]["top_y_split_span_px"] = root["top_y_split_span_px"].asString();
        }
        if (root["side_x_split_span_px"].isString() && root["side_x_split_span_px"].asString() != Config::getins()->config_["identify"]["side_x_split_span_px"].as<std::string>())
        {
            Config::getins()->config_["identify"]["side_x_split_span_px"] = root["side_x_split_span_px"].asString();
        }

        Config::getins()->writeYaml();

        response["success"] = true;
        response["msg"] = "";
        response["data"] = {};
    }
    catch (std::exception &e)
    {
        response["msg"] = "接口调用失败！请求参数：" + req + "。 \n异常内容:" + std::string(e.what());
    }
    return response;
}

/**
 * 查看http服务器配置参数
 * @return
 */
Json::Value ApiEngine::queryHttpSetting()
{
    Json::Value response;
    response["success"] = false;
    try {
        HttpServerConfig httpServerConfig = Config::getins()->getHttpServerConfig();
        Json::Value data;
        data["is_use"] = httpServerConfig.bIsUse;
        data["http_ip"] = httpServerConfig.strIp;
        data["http_port"] = httpServerConfig.iPort;
        data["token_path"] = httpServerConfig.strTokenUrl;
        data["up_result_path"] = httpServerConfig.strUpResultUrl;
        data["device_status_url"] = httpServerConfig.strUpDeviceStatusUrl;
        data["username"] = httpServerConfig.strUserName;
        data["password"] = httpServerConfig.strPassword;

        response["success"] = true;
        response["msg"] = "";
        response["data"] = data;
    }
    catch (std::exception &e)
    {
        response["msg"] = "接口调用失败！ \n异常内容:" + std::string(e.what());
    }
    return response;
}

/**
 * 修改基础配置参数
 * @param req
 * @return
 */
Json::Value ApiEngine::updateHttpSetting(const std::string &req)
{
    Json::Value response;
    response["success"] = false;
    try {
        Json::CharReaderBuilder readerBuilder;
        std::istringstream iss(req);
        Json::Value root;
        std::string errs;
        bool parsingSuccessful = Json::parseFromStream(readerBuilder, iss, &root, &errs);
        if (!parsingSuccessful)
        {
            response["msg"] = "接口调用参数异常，所传数据非json：" + req;
            return response;
        }

        if (root["is_use"].isBool() && root["is_use"].asBool() != Config::getins()->config_["http_server"]["is_use"].as<bool>())
        {
            Config::getins()->config_["http_server"]["is_use"] = root["is_use"].asBool();
        }
        if (root["http_ip"].isString() && root["http_ip"].asString() != Config::getins()->config_["http_server"]["http_ip"].as<std::string>())
        {
            Config::getins()->config_["http_server"]["http_ip"] = root["http_ip"].asString();
        }
        if (root["http_port"].isInt() && root["http_port"].asInt() != Config::getins()->config_["http_server"]["http_port"].as<int>())
        {
            Config::getins()->config_["http_server"]["http_port"] = root["http_port"].asInt();
        }
        if (root["token_path"].isString() && root["token_path"].asString() != Config::getins()->config_["http_server"]["token_path"].as<std::string>())
        {
            Config::getins()->config_["http_server"]["token_path"] = root["token_path"].asString();
        }
        if (root["up_result_path"].isString() && root["up_result_path"].asString() != Config::getins()->config_["http_server"]["up_result_path"].as<std::string>())
        {
            Config::getins()->config_["http_server"]["up_result_path"] = root["up_result_path"].asString();
        }
        if (root["device_status_url"].isString() && root["device_status_url"].asString() != Config::getins()->config_["http_server"]["device_status_url"].as<std::string>())
        {
            Config::getins()->config_["http_server"]["device_status_url"] = root["device_status_url"].asString();
        }
        if (root["username"].isString() && root["username"].asString() != Config::getins()->config_["http_server"]["username"].as<std::string>())
        {
            Config::getins()->config_["http_server"]["username"] = root["username"].asString();
        }
        if (root["password"].isString() && root["password"].asString() != Config::getins()->config_["http_server"]["password"].as<std::string>())
        {
            Config::getins()->config_["http_server"]["password"] = root["password"].asString();
        }

        Config::getins()->writeYaml();

        response["success"] = true;
        response["msg"] = "";
        response["data"] = {};
    }
    catch (std::exception &e)
    {
        response["msg"] = "接口调用失败！请求参数：" + req + "。 \n异常内容:" + std::string(e.what());
    }
    return response;
}

/**
 * 查看http服务器配置参数
 * @return
 */
Json::Value ApiEngine::queryMinioSetting()
{
    Json::Value response;
    response["success"] = false;
    try {
        MinioConfig minioConfig = Config::getins()->getMinioConfig();
        Json::Value data;
        data["is_use"] = minioConfig.bIsUse;
        data["url"] = minioConfig.strUrl;
        data["accesskey"] = minioConfig.strAccessKey;
        data["secretkey"] = minioConfig.strSecretKey;
        data["bucket"] = minioConfig.strBucket;

        response["success"] = true;
        response["msg"] = "";
        response["data"] = data;
    }
    catch (std::exception &e)
    {
        response["msg"] = "接口调用失败！ \n异常内容:" + std::string(e.what());
    }
    return response;
}

/**
 * 修改基础配置参数
 * @param req
 * @return
 */
Json::Value ApiEngine::updateMinioSetting(const std::string &req)
{
    Json::Value response;
    response["success"] = false;
    try {
        Json::CharReaderBuilder readerBuilder;
        std::istringstream iss(req);
        Json::Value root;
        std::string errs;
        bool parsingSuccessful = Json::parseFromStream(readerBuilder, iss, &root, &errs);
        if (!parsingSuccessful)
        {
            response["msg"] = "接口调用参数异常，所传数据非json：" + req;
            return response;
        }

        if (root["is_use"].isBool() && root["is_use"].asBool() != Config::getins()->config_["minio"]["is_use"].as<bool>())
        {
            Config::getins()->config_["minio"]["is_use"] = root["is_use"].asBool();
        }
        if (root["url"].isString() && root["url"].asString() != Config::getins()->config_["minio"]["url"].as<std::string>())
        {
            Config::getins()->config_["minio"]["url"] = root["url"].asString();
        }
        if (root["accesskey"].isString() && root["accesskey"].asString() != Config::getins()->config_["minio"]["accesskey"].as<std::string>())
        {
            Config::getins()->config_["minio"]["accesskey"] = root["accesskey"].asString();
        }
        if (root["secretkey"].isString() && root["secretkey"].asString() != Config::getins()->config_["minio"]["secretkey"].as<std::string>())
        {
            Config::getins()->config_["minio"]["secretkey"] = root["secretkey"].asString();
        }
        if (root["bucket"].isString() && root["bucket"].asString() != Config::getins()->config_["minio"]["bucket"].as<std::string>())
        {
            Config::getins()->config_["minio"]["bucket"] = root["bucket"].asString();
        }

        Config::getins()->writeYaml();

        response["success"] = true;
        response["msg"] = "";
        response["data"] = {};
    }
    catch (std::exception &e)
    {
        response["msg"] = "接口调用失败！请求参数：" + req + "。 \n异常内容:" + std::string(e.what());
    }
    return response;
}

Json::Value ApiEngine::identifyStart()
{
    Json::Value response;
    response["success"] = false;
    try {
        if (g_identify_type)
        {
            response["success"] = true;
            response["msg"] = "程序已处在“识别”状态，请勿重复操作";
            response["data"] = {};
        }
        else
        {
            g_identify_type = 1;
            response["success"] = true;
            response["msg"] = "程序已开启“识别”";
            response["data"] = {};
        }
    }
    catch (std::exception &e)
    {
        response["msg"] = "接口调用失败！ \n异常内容:" + std::string(e.what());
    }
    return response;
}

Json::Value ApiEngine::identifyStop()
{
    Json::Value response;
    response["success"] = false;
    try {
        if (!g_identify_type)
        {
            response["success"] = true;
            response["msg"] = "程序已处在“停止”状态，请勿重复操作";
            response["data"] = {};
        }
        else
        {
            g_identify_type = 0;
            response["success"] = true;
            response["msg"] = "程序已停止“识别”";
            response["data"] = {};
        }
    }
    catch (std::exception &e)
    {
        response["msg"] = "接口调用失败！ \n异常内容:" + std::string(e.what());
    }
    return response;
}