#include "GamePid.h"
#include <tinyxml2.h>
PidData* GamePid::GetPid(const wchar_t* pidName)
{
	auto iter = loadedPid.find(pidName);
	if (iter == loadedPid.end())
	{
		PidData pidData;
		LoadPid(&pidData, pidName);
		loadedPid.insert(std::make_pair(pidName, pidData));
		return &loadedPid.at(pidName);
	}
	return &iter->second;
}

void GamePid::ReloadLanguage()
{
	loadedPid.clear();
}

void GamePid::LoadPid(PidData* outPidData, const wchar_t* pidName)
{
	wchar_t wbuff[MAX_PATH];
	bool languageFolder = false;
	if (pEntityLanguage->GetLength() == 0 || *pEntityLanguage == L"默认")
	{
		swprintf_s(wbuff, L"./data/pid/%s.pid", pidName);
	}
	else
	{
		swprintf_s(wbuff, L"./data/language/%s/pid/%s.pid", pEntityLanguage->GetString(), pidName);
		languageFolder = true;
	}
	//载入文件数据
	FILE* fp = nullptr;
	if (languageFolder)
	{
		//确认翻译文件是否存在
		_wfopen_s(&fp, wbuff, L"rb");
	}
	if (!fp)
	{
		//翻译文件不存在，使用默认文件
		swprintf_s(wbuff, L"./data/pid/%s.pid", pidName);
		_wfopen_s(&fp, wbuff, L"rb");
	}
	if (!fp)
	{
		wchar_t err[MAX_PATH];
		swprintf_s(err, L"pid文件%s无法载入或丢失", wbuff);
		MessageBoxW(AfxGetApp()->GetMainWnd()->m_hWnd, err, L"载入资源错误", MB_ICONERROR);
		return;
	}
	fseek(fp, 0, SEEK_END);
	size_t fileLen = ftell(fp);
	fseek(fp, 0, SEEK_SET);
	std::vector<BYTE> file_buff;
	file_buff.resize(fileLen);
	fread_s(file_buff.data(), file_buff.size(), fileLen, 1, fp);
	fclose(fp);
	std::vector<BYTE> byte_buff;
	size_t len = 0;
	ZLibUncompressData(&byte_buff, &len, file_buff.data(), fileLen);
	LoadPidXML(outPidData, (const wchar_t*)byte_buff.data());
}

void PidLoadXML(std::unordered_map<std::wstring, AniPrep>* aniList, tinyxml2::XMLElement* xmlElement)
{
	if (xmlElement == nullptr)
		return;
	//跳过设定标签
	if (strcmp(xmlElement->Name(), "Animation") == 0)
	{
		AniPrep aniPrep;
		//取动画名称
		std::vector<wchar_t> name;
		UTF8ToUTF16(xmlElement->Attribute("Name"), &name);
		aniPrep.loop = xmlElement->BoolAttribute("Loop");
		aniPrep.speed = xmlElement->IntAttribute("Speed");
		aniPrep.texture_left = xmlElement->IntAttribute("Texture_Left", 16);
		aniPrep.texture_right = xmlElement->IntAttribute("Texture_Right", 16);
		aniPrep.texture_up = xmlElement->IntAttribute("Texture_Up", 16);
		aniPrep.texture_down = xmlElement->IntAttribute("Texture_Down", 16);
		//遍历动画层表
		for (auto p = xmlElement->FirstChildElement(); p != nullptr; p = p->NextSiblingElement())
		{
			//如果不是Layer元素则跳过
			if (strcmp(p->Name(), "Layer") != 0)
				continue;
			AniLayer layer;
			//遍历矩形表
			for (auto t = p->FirstChildElement(); t != nullptr; t = t->NextSiblingElement())
			{
				//如果不是Rect元素则跳过
				if (strcmp(t->Name(), "Frame") != 0)
					continue;
				AniFrame frame;
				frame.id = t->IntAttribute("id");
				frame.offx = t->FloatAttribute("offx");
				frame.offy = t->FloatAttribute("offy");
				layer.frameList.push_back(frame);
			}
			aniPrep.layerList.push_back(layer);
		}
		aniList->insert(std::make_pair(name.data(), aniPrep));
		//遍历子节点
		PidLoadXML(aniList, xmlElement->FirstChildElement());
	}
	//遍历兄弟节点
	PidLoadXML(aniList, xmlElement->NextSiblingElement());
}

void GamePid::LoadPidXML(PidData* outPidData, const wchar_t* xml)
{
	std::vector<char> utf8_buff;
	UTF16ToUTF8(xml, &utf8_buff);
	tinyxml2::XMLDocument xmlDoc;
	xmlDoc.Parse(utf8_buff.data());
	tinyxml2::XMLElement* elem = nullptr;
	//寻找TileSet元素
	for (tinyxml2::XMLElement* pElem = xmlDoc.FirstChildElement(); pElem; pElem = pElem->NextSiblingElement())
	{
		if (!strcmp(pElem->Name(), "TileSet"))
		{
			elem = pElem;
			break;
		}	
	}
	if (elem)
	{
		//读取TileSet
		outPidData->pid_tile_w = elem->IntAttribute("TileW");
		outPidData->pid_tile_h = elem->IntAttribute("TileH");
		outPidData->bInterArea = elem->BoolAttribute("InterArea");
	}
	//寻找Pid元素
	elem = nullptr;
	for (tinyxml2::XMLElement* pElem = xmlDoc.FirstChildElement(); pElem; pElem = pElem->NextSiblingElement())
	{
		if (!strcmp(pElem->Name(), "Pid"))
		{
			elem = pElem;
			break;
		}	
	}
	if (elem)
	{
		//遍历所有的Rect元素
		for (elem = elem->FirstChildElement(); elem; elem = elem->NextSiblingElement())
		{
			//跳过不是Rect的元素
			if (strcmp(elem->Name(), "Rect"))
				continue;
			//给step赋值
			MyRect rc;
			auto& step = outPidData->pidList;
			rc.left = elem->FloatAttribute("left");
			rc.right = elem->FloatAttribute("right");
			rc.top = elem->FloatAttribute("top");
			rc.bottom = elem->FloatAttribute("bottom");
			int id = elem->IntAttribute("id");
			step[id] = rc;
		}
	}
	//寻找Ani元素
	elem = nullptr;
	for (tinyxml2::XMLElement* pElem = xmlDoc.FirstChildElement(); pElem; pElem = pElem->NextSiblingElement())
	{
		if (!strcmp(pElem->Name(), "Ani"))
		{
			elem = pElem;
			break;
		}
	}
	if (elem)
	{
		PidLoadXML(&outPidData->aniList, elem->FirstChildElement());
	}
}
