#include "DataStruct.h"
#include "common/JsonN.h"
#include "common/Utils.h"

static map<string, int> g_mapTopicDeviceType =
{
	{"EMS_YT", 101}, {"EMS_YX", 101}, {"EMS_YC", 101},
	{"PCU_YC", 103}, {"PCU_YX", 103},
	{"PCS_YC", 102}, {"PCS_YX", 102},
	{"BMS_YC", 104},
	{"BCU_YC", 105}, {"BCU_YX", 105},
	{"MEM_YC", 3},
	{"TH_YC", 10},
	{"Fire40_YX", 7},
	{"Cooling_YC", 14},
	{"Cooling_YX", 14},
	{"Gateway_YC", 15},
	{"Gateway_YX", 15},
	{"Charger_YC", 106}
};

// key: tpoic, 子key: addr
std::map<std::string, std::map<std::string, RegAddrUnit>> REGAddr::s_mapReg;

std::map<int, std::vector<DeviceParamAddr>> REGAddr::s_mapDeviceAddrParam;
std::map<int, std::vector<std::string>> REGAddr::s_mapDeviceAddrCurve;
std::map<int, std::map<std::string, std::map<std::string, std::string>>> REGAddr::g_mapRegAddrValStr;

// key: 设备类型， 子key： addr
std::map<int, std::map<std::string, RegAddrUnit>> REGAddr::g_mapRegDeviceType;

void REGAddr::load(std::string filename)
{
	njson json;
	JSON::load(filename, json);

	// 遍历 JSON 对象
	for (auto& jsonitem : json.items())
	{
		std::string name = jsonitem.key(); // topic名称
		int deviceType = g_mapTopicDeviceType[name];

		auto& jsonnodeItem = jsonitem.value();
		//int count = jsonnodeItem["count"];
		auto jsonaddrs = jsonnodeItem["addr"];

		auto& mapItem = s_mapReg[name];
		int size = 0;
		for (int i = 0; i<2; ++i)
		{
			for (auto& item : jsonaddrs)
			{
				std::string addr = item["key"];
				std::string datatype = JSON::read<std::string>(item, "datatype");
				std::string remark = JSON::read<std::string>(item, "remark");
				std::string name = JSON::read<std::string>(item, "name");
				int alert = JSON::read<int>(item, "alert");
				g_mapRegDeviceType[deviceType][addr] = mapItem[addr] = RegAddrUnit(addr, datatype, alert, name, remark);
			}
		}
	}
}


void REGAddr::loadParamAddr(std::string filename)
{
	try
	{
		njson json;
		if (!JSON::load(filename, json))
		{
			spdlog::error("[device] json load param addr error, filename={}", filename);
		}
		for (auto& jsonitem : json.items())
		{
			std::string key = jsonitem.key();
			auto& jsonnodeItem = jsonitem.value();

			int deviceType = jsonnodeItem["deviceType"];
			auto& vec = s_mapDeviceAddrParam[deviceType];
			for (auto& v : jsonnodeItem["addrYC"])
			{
				std::string name = JSON::get<std::string>(v[0]);
				std::string addr = JSON::get<std::string>(v[1]);
				std::string defaultVal = JSON::get<std::string>(v[2]);
				std::string unit = JSON::get<std::string>(v[3]);
				float ratio = Utils::toFloat(JSON::get<string>(v[4]));
				vec.push_back(DeviceParamAddr(name, addr, defaultVal, unit, ratio));
			}
			if (jsonnodeItem.contains("addrCurve"))
			{
				auto& vec = s_mapDeviceAddrCurve[deviceType];
				for (auto& v : jsonnodeItem["addrCurve"])
				{
					vec.push_back(v.get<std::string>());
				}
			}
			if (jsonnodeItem.contains("valstr"))
			{
				auto& mapDT = g_mapRegAddrValStr[deviceType];
				for (auto& itemaddr : jsonnodeItem["valstr"].items())
				{
					string addr = itemaddr.key();
					auto& mapAddr = mapDT[addr];
					for (auto& itemval: itemaddr.value().items())
					{
						string key = itemval.key();
						mapAddr[key] = itemval.value().get<std::string>();
					}
				}
			}
		}
	}
	catch (nlohmann::json::parse_error& e)
	{
		spdlog::error("[device] parse [{}] error: ", filename, e.what());
	}
}

std::map<std::string, RegAddrUnit>* REGAddr::getRegMap(std::string name)
{
	auto iter = s_mapReg.find(name);
	if (iter != s_mapReg.end())
	{
		return &(iter->second);
	}
	return nullptr;
}

std::map<std::string, RegAddrUnit>* REGAddr::getRegMapByDeviceType(int deviceType)
{
	auto iter = g_mapRegDeviceType.find(deviceType);
	if (iter != g_mapRegDeviceType.end())
	{
		return &(iter->second);
	}
	return nullptr;
}

std::vector<DeviceParamAddr>& REGAddr::GetDeviceParamAddrs(int deviceType)
{
	static std::vector<DeviceParamAddr> vecAddrs = {};
	auto iter = s_mapDeviceAddrParam.find(deviceType);
	if (iter != s_mapDeviceAddrParam.end())
	{
		return iter->second;
	}
	return vecAddrs;
}