#include "Policy.h"
#include "common/Spdlogger.h"
#include "Utils.h"

void SysPolicy::setFields(Fields& fields)
{
	this->policyId = fields.get<int>("policy_id");
	this->type = fields.get<int>("type");  // policy_type
	this->name = fields.value("name"); // policy_name
	this->value = fields.value("value");

	this->parseValue(value);
}


/// type=1: 峰谷套利
static void ParseJsonType1(njson& json)
{
}

void SysPolicy::getGatewayJsonPrice(njson& json)
{
}

// 1：峰谷套利，2：配网增容，3：应急供电，4：并网保电，5：自定时段
void SysPolicy::parseValue(std::string jsonstr)
{
	njson jsonroot;
	if (!JSON::parse(jsonstr, jsonroot))
	{
		spdlog::error("[policy] json parse policy value error, policy_id={}, value={}", policyId, jsonstr);
		return;
	}

	// 读取电价
	if (jsonroot.contains("price"))
	{
		auto& jsonArrayPrice = jsonroot["price"];
		for (int i = 0; i<vecPrice.size(); ++i)
		{
			if (i<jsonArrayPrice.size())
			{
				vecPrice[i] = Utils::toFloat(jsonArrayPrice[i].get<std::string>());
			}
		}
	}

	if (this->type == 1 || this->type == 5)
	{
		this->parseJsonPeriods(jsonroot);
	}
}

void SysPolicy::parseJsonPeriods(njson& jsonroot)
{
	if (!jsonroot.contains("period"))
	{
		spdlog::error("[policy] json parse policy value error, [period] is not exist, value={}", jsonroot.dump());
		return;
	}
	auto& json = jsonroot["period"];
	if (!json.is_array())
	{
		spdlog::error("[policy] json parse policy value error, [period] is not array, value={}", json.dump());
		return;
	}
		
	// 1: 谷，2：平，3：峰，4：尖
	if (this->type == 1) // 峰谷套利
	{
		vecPeriods1.clear();
		for (int i = 0; i<json.size() && i<12; ++i) // 月份信息，最多12个月
		{
			if (json[i].size() > 0)
			{
				vecPeriods1.push_back(std::vector<std::pair<std::string, std::string>>());
				for (auto& itemMonth: json[i])
				{
					if (itemMonth.size() >=2) { vecPeriods1[i].push_back({itemMonth[0], itemMonth[1]}); }
				}
			}
		}
	}
	else if (this->type == 5)
	{
		//{
		//	"period":[
		//		{"charge_time":[],"discharge_time":[],"charge_power":"","discharge_power":""},
		//		{"charge_time":[],"discharge_time":[],"charge_power":"","discharge_power":""}
		//	],
		// "price":["0.00","0.00","0.00","0.00"]
		//}
		vecPeriods1.clear();
		for (int i = 0; i<json.size(); ++i) // 一充一放或二充二放
		{
			vecPeriods1.push_back(std::vector<std::pair<std::string, std::string>>());
			auto& item = json[i];
			if (item.contains("charge_time") && item["charge_time"].size() >= 2)
			{
				auto& jsonP = item["charge_time"];
				vecPeriods1[i].push_back({jsonP[0], "谷"}); // 第一/二次充电开始
				vecPeriods1[i].push_back({jsonP[1], ""}); // 第一/二次充电结束
			}
			if (item.contains("discharge_time") && item["discharge_time"].size() >= 2)
			{
				auto& jsonP = item["discharge_time"];
				vecPeriods1[i].push_back({jsonP[0], "尖"}); // 第一/二次放电开始
				vecPeriods1[i].push_back({jsonP[1], ""}); // 第一/二次放电结束
			}
		}
	}
}

static void PeriodsTimeStrToInt(std::string str, int& h, int& m)
{
	int pos = str.find(":");
	if (pos != std::string::npos)
	{
		h = Utils::toInt(str.substr(0, pos));
		m = Utils::toInt(str.substr(pos+1));
	}
}

// 0: 无，1：尖；2：峰；3：平；4：谷；5：深谷
static void PeriodsStrToInt(std::string str, int& v)
{
	if (str == "无") v = 0;
	else if (str == "尖") v = 1;
	else if (str == "峰") v = 2;
	else if (str == "平") v = 3;
	else if (str == "谷") v = 4;
	else if (str == "深谷") v = 5;
}

void SysPolicy::getGatewayJsonPeriods(njson& json)
{
	if (type == 1)
	{
		for (auto& itemMonth: vecPeriods1)
		{
			njson jsonArrayMonth = njson::array();
			for (auto& item: itemMonth)
			{
				int h = 0; int m = 0;
				PeriodsTimeStrToInt(item.first, h, m);
				int p = 1;
				PeriodsStrToInt(item.second, p);
				jsonArrayMonth.push_back({h, m, p});
			}
			json.push_back(jsonArrayMonth);
		}
	}
	else if (type == 5)
	{
		if (vecPeriods1.size()>0)
		{
			map<string, vector<int>> mapT;
			for (int i = 0; i<vecPeriods1.size(); ++i)
			{
				for (auto& item: vecPeriods1[i])
				{
					int h = 0; int m = 0;
					PeriodsTimeStrToInt(item.first, h, m);
					int p = 0;
					PeriodsStrToInt(item.second, p);
					char str[5] = {};
					sprintf(str, "%02d:%02d", h, m);
					mapT[str] = {h, m, p};
				}
			}
			njson jsonArray = njson::array();
			for (auto& item: mapT)
			{
				if (jsonArray.size() == 0 && item.first != "00:00")
				{
					jsonArray.push_back({0, 0, 0});
				}
				jsonArray.push_back(item.second);
			}
			json.push_back(jsonArray);
		}
	}
}