#include "GameMap.h"
#include "MyView.h"
#include "GamePxa.h"
#include "ScriptLuaFunc.h"
#include "main.h"
#include "TranslateLua.h"
extern HWND hwnd;
GameMap::~GameMap()
{
	if (scriptL)
		lua_close(scriptL);
}

void GameMap::Init(MyView* pView, GamePxa* pGamePxa, void* pScriptCmd)
{
	this->pView = pView;
	this->pGamePxa = pGamePxa;
	this->scriptCmd = pScriptCmd;
}
//main.cpp
void GameMap::GetMapSize(int** ppMapW, int** ppMapH)
{
	*ppMapW = &mapW;
	*ppMapH = &mapH;
}

std::wstring GameMap::GetMapFileName()
{
	return mapfileName;
}

std::list<MyMapLayer>* GameMap::GetLayerList()
{
	return &layerList;
}

MyMapLayer* GameMap::GetMapLayer(const wchar_t* layerName)
{
	auto iter = queryMapLayer.find(layerName);
	if (iter != queryMapLayer.end())
		return iter->second;
	else
		return nullptr;
}

lua_State** GameMap::GetScriptLPtr()
{
	return &scriptL;
}

MyView* GameMap::GetView()
{
	return pView;
}

void GameMap::LoadMap(const wchar_t* mapfileName)
{
	this->mapfileName = mapfileName;
	wchar_t wbuff[MAX_PATH];
	std::vector<char> utf8;
	std::vector<wchar_t> utf16;
	//载入地图数据
	swprintf_s(wbuff, L"./data/map/%s.pxm", mapfileName);
	FILE* fp;
	_wfopen_s(&fp, wbuff, L"rb");
	if (!fp)
	{
		wchar_t err[MAX_PATH];
		swprintf_s(err, L"地图文件%s无法载入或丢失", wbuff);
		MessageBoxW(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);
	LoadMapXML((const wchar_t*)byte_buff.data());
	pView->count_w = mapW;
	pView->count_max = pView->count_w * mapH;
	if (!scriptCmd)
		return;
	//载入地图脚本
	if (scriptL)
		lua_close(scriptL);
	scriptL = NewScriptL(scriptCmd);
	//写入一个路径变量
	luaL_dostring(scriptL, "global_path=\"./data/\"");
	//运行全局脚本
	if (luaL_dofile(scriptL, "./data/global.lua") != LUA_OK)
	{
		auto err = lua_tostring(scriptL, -1);
		UTF8ToUTF16(err, &utf16);
		MessageBox(hwnd, utf16.data(), L"在global脚本发生错误", MB_ICONWARNING);
		lua_pop(scriptL, 1);
	}
	//载入地图脚本数据
	swprintf_s(wbuff, L"./data/map/%s.lua", mapfileName);
	UTF16ToUTF8(wbuff, &utf8);
	if (luaL_dofile(scriptL, utf8.data()) != LUA_OK)
	{
		auto err = lua_tostring(scriptL, -1);
		UTF8ToUTF16(err, &utf16);
		wchar_t title[MAX_PATH];
		swprintf_s(title, L"在%s脚本发生错误", wbuff);
		MessageBox(hwnd, utf16.data(), title, MB_ICONWARNING);
		lua_pop(scriptL, 1);
	}
	ReloadLanguage();
}

void GameMap::LoadMapXML(const wchar_t* xml)
{
	std::vector<char> xml_utf8;
	UTF16ToUTF8(xml, &xml_utf8);
	tinyxml2::XMLDocument xmlDoc;
	xmlDoc.Parse(xml_utf8.data());
	tinyxml2::XMLElement* elem = nullptr;
	//寻找Pxm元素
	for (tinyxml2::XMLElement* pElem = xmlDoc.FirstChildElement(); pElem; pElem = pElem->NextSiblingElement())
	{
		if (!strcmp(pElem->Name(), "Pxm"))
		{
			elem = pElem;
			break;
		}	
	}
	if (!elem)
	{
		MessageBoxW(hwnd, L"载入地图XML文件错误，找不到Pxm元素", L"载入资源错误", MB_ICONERROR);
		return;
	}
	//读取地图数据
	std::priority_queue<MyMapLayer> sortList;
	std::vector<wchar_t> wchar_buff;
	UTF8ToUTF16(elem->Attribute("MapName"), &wchar_buff);
	mapName = wchar_buff.data();
	mapW = elem->IntAttribute("MapW");
	mapH = elem->IntAttribute("MapH");
	//遍历所有Layer元素
	for (auto p = elem->FirstChildElement(); p; p = p->NextSiblingElement())
	{
		//跳过不是Layer的元素
		if (strcmp(p->Name(), "Layer"))
			continue;
		MyMapLayer layer;
		//图层名
		UTF8ToUTF16(p->Attribute("Name"), &wchar_buff);//读取图层名
		layer.layerName = wchar_buff.data();
		//图层可见
		layer.visible = p->BoolAttribute("Visiable");
		//地形组
		UTF8ToUTF16(p->Attribute("PxaName"), &wchar_buff);//读取地形组
		layer.pxaName = wchar_buff.data();
		//图层类型
		layer.layerType = p->IntAttribute("LayerType");
		//图层属性
		layer.offx = p->FloatAttribute("OffX");//x偏移
		layer.offy = p->FloatAttribute("OffY");//y偏移
		layer.myFar = p->FloatAttribute("Far");//距离
		//循环背景层属性
		layer.loopH = p->BoolAttribute("LoopH");//水平循环显示
		layer.loopV = p->BoolAttribute("LoopV");//垂直循环显示
		layer.loopNeg = p->BoolAttribute("LoopNeg");//单循环另一侧显示
		layer.speedH = p->FloatAttribute("SpeedH");//水平平移速度
		layer.speedV = p->FloatAttribute("SpeedV");//垂直平移速度
		//通用
		layer.order = p->FloatAttribute("Order");//图层顺序
		layer.jumpFrame_counter = layer.jumpFrame = p->IntAttribute("JumpFrame");
		//光层
		layer.dayLight = p->FloatAttribute("DayLight", 1.0f);//天光
		layer.tinyHSV[0] = p->FloatAttribute("tinyHSV_H", 0.0f);//细微HSV调整
		layer.tinyHSV[1] = p->FloatAttribute("tinyHSV_S", 0.0f);//细微HSV调整
		layer.tinyHSV[2] = p->FloatAttribute("tinyHSV_V", 0.0f);//细微HSV调整
		layer.lightConst = p->FloatAttribute("LightConst", 1.0f);//收到来自其他层的光线影响比例
		//颜色调整
		layer.color = (DWORD)p->Unsigned64Attribute("Color");//混合颜色
		//绘制剪切区域
		layer.enableClipZone = p->BoolAttribute("EnableClipZone");//启用绘制剪切区域
		layer.clipZone.top = p->FloatAttribute("ClipUp");//剪切区域上
		layer.clipZone.bottom = p->FloatAttribute("ClipDown");//剪切区域上
		layer.clipZone.left = p->FloatAttribute("ClipLeft");//剪切区域上
		layer.clipZone.right = p->FloatAttribute("ClipRight");//剪切区域上
		auto& step_pxm = layer.step_pxm;
		auto& step_pxe = layer.step_pxe;
		//遍历ID元素
		for (auto t = p->FirstChildElement(); t != nullptr; t = t->NextSiblingElement())
		{
			//如果是Rect元素则跳过
			if (!strcmp(t->Name(), "ID"))
			{
				int pxmX = t->IntAttribute("pxmX");
				int pxmY = t->IntAttribute("pxmY");
				int pxaX = t->IntAttribute("pxaX");
				int pxaY = t->IntAttribute("pxaY");
				step_pxm.insert(std::make_pair(MAKELONG(pxmX, pxmY), MAKELONG(pxaX, pxaY)));
			}
			//如果是ENT元素
			else if (!strcmp(t->Name(), "ENT"))
			{
				EntityLoad entityLoad;
				UTF8ToUTF16(t->Attribute("name"), &wchar_buff);
				entityLoad.name = wchar_buff.data();
				entityLoad.x = t->IntAttribute("x");
				entityLoad.y = t->IntAttribute("y");
				UTF8ToUTF16(t->Attribute("eid"), &wchar_buff);
				entityLoad.eid = wchar_buff.data();
				UTF8ToUTF16(t->Attribute("event"), &wchar_buff);
				entityLoad.eventName = wchar_buff.data();
				wchar_buff.resize(1);
				wchar_buff[0] = 0;
				UTF8ToUTF16(t->Attribute("arg"), &wchar_buff);
				entityLoad.arg = wchar_buff.data();
				wchar_buff.resize(1);
				wchar_buff[0] = 0;
				UTF8ToUTF16(t->Attribute("arg2"), &wchar_buff);
				entityLoad.arg2 = wchar_buff.data();
				wchar_buff.resize(1);
				wchar_buff[0] = 0;
				UTF8ToUTF16(t->Attribute("arg3"), &wchar_buff);
				entityLoad.arg3 = wchar_buff.data();
				auto& flag = entityLoad.flag;
				flag.tCheck = t->BoolAttribute("tCheck");
				flag.tTouch = t->BoolAttribute("tTouch");
				flag.tDeath = t->BoolAttribute("tDeath");
				flag.tCrush = t->BoolAttribute("tCrush");
				flag.tHurt = t->BoolAttribute("tHurt");
				flag.tDamage = t->BoolAttribute("tDamage");
				flag.fShow = t->BoolAttribute("fShow");
				flag.fHide = t->BoolAttribute("fHide");
				flag.skShow = t->BoolAttribute("skShow");
				flag.skHide = t->BoolAttribute("skHide");
				flag.d0Show = t->BoolAttribute("d0Show");
				flag.d0Hide = t->BoolAttribute("d0Hide");
				flag.d1Show = t->BoolAttribute("d1Show");
				flag.d1Hide = t->BoolAttribute("d1Hide");
				flag.lr = t->BoolAttribute("lr");
				flag.text = t->BoolAttribute("text");
				flag.save = t->BoolAttribute("save");
				flag.simpAni = t->BoolAttribute("simpAni");
				step_pxe.push_back(entityLoad);
			}
		}
		//更新到数组的版本
		auto& PxaData = *pGamePxa->GetPxa(layer.pxaName.c_str());
		layer.UpdatePxmArr(PxaData.pxaArr_w);
		sortList.push(layer);
	}
	//插入
	layerList.clear();
	while (!sortList.empty())
	{
		layerList.push_front(sortList.top());
		sortList.pop();
	}
	queryMapLayer.clear();
	for (auto& p : layerList)
		queryMapLayer.insert(std::make_pair(p.layerName, &p));
}

const wchar_t* GameMap::GetMapShowName()
{
	auto iter = roomNameTable.find(mapName);
	if (iter != roomNameTable.end())
		return iter->second.c_str();
	return mapName.c_str();
}

void GameMap::ReloadLanguage()
{
	if (!scriptL)
		return;
	std::vector<char> utf8;
	std::vector<wchar_t> utf16;
	char buff[MAX_PATH];
	wchar_t wbuff[MAX_PATH];
	//载入翻译的脚本文件（如果有）
	if (language_now.length() > 0)
	{
		FILE* fp = nullptr;
		//载入翻译的全局脚本
		swprintf_s(wbuff, L"./data/language/%s/global.lua", language_now.c_str());
		_wfopen_s(&fp, wbuff, L"rb");
		if (fp)
		{
			fclose(fp);
			//写入global路径的全局变量
			UTF16ToUTF8(language_now.c_str(), &utf8);
			sprintf_s(buff, "global_path=\"./data/language/%s/\"", utf8.data());
			luaL_dostring(scriptL, buff);
			//文件存在，则载入
			UTF16ToUTF8(wbuff, &utf8);
			if (luaL_dofile(scriptL, utf8.data()) != LUA_OK)
			{
				auto err = lua_tostring(scriptL, -1);
				wchar_t errBuff[MAX_PATH];
				swprintf_s(errBuff, L"在%s的global脚本发生错误", language_now.c_str());
				UTF8ToUTF16(err, &utf16);
				MessageBox(hwnd, utf16.data(), errBuff, MB_ICONWARNING);
				lua_pop(scriptL, 1);
			}
		}
		//载入对应翻译的房间脚本
		swprintf_s(wbuff, L"./data/language/%s/script/%s.lua", language_now.c_str(), mapfileName.c_str());
		_wfopen_s(&fp, wbuff, L"rb");
		if (fp)
		{
			fclose(fp);
			//文件存在，则载入
			UTF16ToUTF8(wbuff, &utf8);
			if (luaL_dofile(scriptL, utf8.data()) != LUA_OK)
			{
				auto err = lua_tostring(scriptL, -1);
				UTF8ToUTF16(err, &utf16);
				wchar_t title[MAX_PATH];
				swprintf_s(title, L"在%s脚本发生错误", wbuff);
				MessageBox(hwnd, utf16.data(), title, MB_ICONWARNING);
				lua_pop(scriptL, 1);
			}
		}
		//重新载入翻译的房间名表
		roomNameTable.clear();
		//寻找文件
		swprintf_s(wbuff, L"./data/language/%s/roomName.lua", language_now.c_str());
		_wfopen_s(&fp, wbuff, L"rb");
		if (fp)
		{
			fclose(fp);
			//文件存在，则载入
			UTF16ToUTF8(wbuff, &utf8);
			auto L = NewTranslateLua();
			if (luaL_dofile(L, utf8.data()) != LUA_OK)
			{
				auto err = lua_tostring(L, -1);
				UTF8ToUTF16(err, &utf16);
				wchar_t title[MAX_PATH];
				swprintf_s(title, L"在%s脚本发生错误", wbuff);
				MessageBox(hwnd, utf16.data(), title, MB_ICONWARNING);
				lua_pop(L, 1);
			}
			lua_close(L);
		}
	}
}

void GameMap::CMP(std::wstring layerNameCopyFrom, std::wstring layerNameCopyTo, std::vector<LONG>* pPosArr)
{
	MyMapLayer* layerCopyFrom = nullptr;
	MyMapLayer* layerCopyTo = nullptr;
	if (pPosArr)
		pPosArr->clear();
	for (auto& p : layerList)
	{
		if (p.layerName == layerNameCopyFrom)
			layerCopyFrom = &p;
		else if (p.layerName == layerNameCopyTo)
			layerCopyTo = &p;
		if (layerCopyFrom && layerCopyTo)
			break;
	}
	if (!(layerCopyFrom && layerCopyTo))
		return;
	int pxaArr_w = pGamePxa->GetPxa(layerCopyTo->pxaName.c_str())->pxaArr_w;
	for (auto& p : layerCopyFrom->step_pxm)
	{
		if (p.second == 0)
			continue;
		layerCopyTo->step_pxm[p.first] = p.second;
		layerCopyTo->UpdatePxmArr(pxaArr_w);
		if (pPosArr)
			pPosArr->push_back(p.first);
	}
}

void GameMap::FullLight()
{
	for (auto& p : layerList)
		p.dayLight = 1;
}

void GameMap::ReloadGameMapScript()
{
	if (mapfileName.length() == 0)
		return;
	wchar_t wbuff[MAX_PATH];
	std::vector<char> utf8;
	std::vector<wchar_t> utf16;
	//载入地图数据
	swprintf_s(wbuff, L"./data/map/%s.pxm", mapfileName.c_str());
	FILE* fp;
	_wfopen_s(&fp, wbuff, L"rb");
	if (!fp)
	{
		wchar_t err[MAX_PATH];
		swprintf_s(err, L"地图文件%s无法载入或丢失", wbuff);
		MessageBoxW(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);
	LoadMapXML((const wchar_t*)byte_buff.data());
	//载入地图脚本
	if (scriptL)
		lua_close(scriptL);
	scriptL = NewScriptL(scriptCmd);
	//写入一个路径变量
	luaL_dostring(scriptL, "global_path=\"./data/\"");
	//运行全局脚本
	if (luaL_dofile(scriptL, "./data/global.lua") != LUA_OK)
	{
		auto err = lua_tostring(scriptL, -1);
		UTF8ToUTF16(err, &utf16);
		MessageBox(hwnd, utf16.data(), L"在global脚本发生错误", MB_ICONWARNING);
		lua_pop(scriptL, 1);
	}
	//载入地图脚本数据
	swprintf_s(wbuff, L"./data/map/%s.lua", mapfileName.c_str());
	UTF16ToUTF8(wbuff, &utf8);
	if (luaL_dofile(scriptL, utf8.data()) != LUA_OK)
	{
		auto err = lua_tostring(scriptL, -1);
		UTF8ToUTF16(err, &utf16);
		wchar_t title[MAX_PATH];
		swprintf_s(title, L"在%s脚本发生错误", wbuff);
		MessageBox(hwnd, utf16.data(), title, MB_ICONWARNING);
		lua_pop(scriptL, 1);
	}
	ReloadLanguage();
}

void MyMapLayer::UpdatePxmArr(int pxaArr_w)
{
	pxmArr_w = 0;
	pxmArr_h = 0;
	for (auto& p : step_pxm)
	{
		auto x = LOWORD(p.first);
		auto y = HIWORD(p.first);
		if (x > pxmArr_w)
			pxmArr_w = x;
		if (y > pxmArr_h)
			pxmArr_h = y;
	}
	//是宽度所以+1
	pxmArr_w++;
	pxmArr_h++;
	pxmArr.resize(pxmArr_w * pxmArr_h);
	std::fill(pxmArr.begin(), pxmArr.end(), 0);
	//把所有数据拷贝进数组
	for (auto& p : step_pxm)
	{
		auto x = LOWORD(p.first);
		auto y = HIWORD(p.first);
		auto pxaX = LOWORD(p.second);
		auto pxaY = HIWORD(p.second);
		pxmArr[y * pxmArr_w + x] = pxaY * pxaArr_w + pxaX;
	}
}

bool MyMapLayer::operator<(const MyMapLayer& r) const
{
	return order > r.order;
}
