#include "Config.h"

#include <fstream>

#include "common/JsonN.h"
#include "common/Spdlogger.h"
#include "AppData.h"
#include "protocol/MqttEntity.h"

AppOption Config::option;

bool Config::init(std::string filename)
{
    njson jsonroot;
    bool ret = JSON::load(filename, jsonroot);
    if (!ret)
    {
        spdlog::error("[config] load config file failed, filename={}", filename);
        return false;
    }
    spdlog::info("[config] load config file success, filename={}", filename);

    JSON::read(jsonroot, "debug", option.debug);
    JSON::read(jsonroot, "weburl", option.webSrvUrl);
    JSON::read(jsonroot, "launchdate", option.lunchDate);
    JSON::read(jsonroot, "exportpath", option.exportpath);
    JSON::read(jsonroot, "windowEnabled", option.windowEnabled);

    if (jsonroot.contains("database"))
    {
        njson& json = jsonroot.at("database");
        JSON::read(json, "host", option.database.host);
        JSON::read(json, "port", option.database.port);
        JSON::read(json, "user", option.database.user);
        JSON::read(json, "passwd", option.database.passwd);
        JSON::read(json, "dbname", option.database.dbname);
        spdlog::info("[config] parse database success. host={}", option.database.host);
    }
    else
    {
        spdlog::error("[config] parse database failed: not found.");
    }

    if (jsonroot.contains("http"))
    {
        njson& json = jsonroot.at("http");
        JSON::read(json, "token", option.http.useToken);
        JSON::read(json, "port", option.http.port);
        JSON::read(json, "encryption", option.http.encryption);
        JSON::read(json, "encryptKey", option.http.encryptKey);    }
    else
    {
        spdlog::error("[config] parse http failed: not found.");
    }

    if (jsonroot.contains("mqtt"))
    {
        njson& json = jsonroot.at("mqtt");
        JSON::read(json, "host", option.mqtt.host);
        JSON::read(json, "username", option.mqtt.username);
        JSON::read(json, "password", option.mqtt.password);
        JSON::read(json, "interval", option.mqtt.interval);
    }
    else
    {
        spdlog::error("[config] parse mqtt failed: not found.");
    }

    if (jsonroot.contains("view"))
    {
        njson& json = jsonroot["view"];
        JSON::read(json, "latitude", option.view.latitude);
        JSON::read(json, "longitude", option.view.longitude);
        JSON::read(json, "altitude", option.view.altitude);
    }
    else
    {
        spdlog::error("[config] parse view failed: not found.");
    }

    if (jsonroot.contains("video"))
    {
        njson& json = jsonroot["video"];
        for (auto& item: json.items())
        {
            auto& key = item.key();
            auto& jsonItem = item.value();
            auto& itemVideo = option.mapVideo[key];
            JSON::read(jsonItem, "host", itemVideo.host);
            JSON::read(jsonItem, "port", itemVideo.port);
            JSON::read(jsonItem, "user", itemVideo.user);
            JSON::read(jsonItem, "passwd", itemVideo.passwd);
        }
    }
    else
    {
        spdlog::error("[config] parse video failed: not found.");
    }

    if (jsonroot.contains("topic"))
    {
        njson& json = jsonroot["topic"];
        for (auto& item: json.items())
        {
            auto& key = item.key();
            auto& jsonItem = item.value();
            auto& info = MqttClient::s_mapTopicInfo[key];
            info.name = key;
            JSON::read(jsonItem, "deviceType", info.deviceType);
            JSON::read(jsonItem, "polling", info.polling);
            JSON::read(jsonItem, "enabled", info.enabled);
        }
    }

    if (jsonroot.contains("statistics"))
    {
        njson& json = jsonroot["statistics"];
        JSON::read(json, "enabled", option.stat.enabled);
        JSON::read(json, "interval", option.stat.interval);
        if (option.stat.interval <= 0) { option.stat.interval = 60; }
    }
    return true;
}


AppOption::VideoInfo* Config::getVideoInfo(std::string name)
{
    auto iter = option.mapVideo.find(name);
    if (iter!=option.mapVideo.end())
    {
        return &(iter->second);
    }
    return nullptr;
}