#include "Npk.h"
#include <fstream>
#include <mutex>
std::mutex Npk_ImgMutex;
std::mutex Npk_PngMutex;

class ReadNpk :public std::ifstream
{
	const BYTE Key[256] = { 112,117,99,104,105,107,111,110,64,110,101,111,112,108,101,32,100,117,110,103,101,111,110,32,97,110,100,32,102,105,103,104,116,101,114,32,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,68,78,70,0 };

public:
	//char* 转整数
	int CharToInt(char* Str)
	{
		return *(int*)Str;
	}

	//char* 转Long
	long CharToLong(char* Str)
	{
		return *(long long*)Str;
	}

	//读整数
	int ReadInt()
	{
		char* CountBuffer = new char[4];
		for (int i = 0; i < 4; i++)
		{
			this->get(CountBuffer[i]);
		}
		int Count = CharToInt(CountBuffer);
		delete[]CountBuffer;
		return Count;
	}

	//读字符串
	std::string ReadString()
	{
		char* CharBuffer = new char[1024];
		this->get(CharBuffer, 1024, '\0');
		std::string Str = CharBuffer;
		delete[]CharBuffer;
		this->seekg(1, std::ios::cur);
		return Str;
	}

	//读取信息
	std::string ReadInfo()
	{
		char* CharBuffer = new char[256];
		char var;
		int i = 0;
		while (i < 256)
		{
			this->get(var);
			CharBuffer[i] = var ^ Key[i];
			++i;
		}
		std::string Str = CharBuffer;
		delete[] CharBuffer;
		return Str;
	}

	//读LONG
	int ReadLong()
	{
		char* CountBuffer = new char[8];
		for (int i = 0; i < 8; i++)
		{
			this->get(CountBuffer[i]);
		}
		long Count = CharToLong(CountBuffer);
		delete[]CountBuffer;
		return Count;
	}

	//读指定长度数据
	BYTE* ReadCustomSize(int Size)
	{
		BYTE* CharBuffer = new BYTE[Size];
		for (int j = 0; j < Size; j++)
		{
			char var;
			this->get(var);
			CharBuffer[j] = var;
		}
		return CharBuffer;
	}

};

void ReadColor(BYTE* Tab, int Type, BYTE* SaveByte, int Offset)
{
	BYTE a = 0;
	BYTE r = 0;
	BYTE g = 0;
	BYTE b = 0;
	switch (Type)
	{
	case 0x0e:
		a = (byte)(Tab[1] >> 7);
		r = (byte)((Tab[1] >> 2) & 0x1f);
		g = (byte)((Tab[0] >> 5) | ((Tab[1] & 3) << 3));
		b = (byte)(Tab[0] & 0x1f);
		a = (byte)(a * 0xff);
		r = (byte)((r << 3) | (r >> 2));
		g = (byte)((g << 3) | (g >> 2));
		b = (byte)((b << 3) | (b >> 2));
		break;
	case 0x0f:
		a = (byte)(Tab[1] & 0xf0);
		r = (byte)((Tab[1] & 0xf) << 4);
		g = (byte)(Tab[0] & 0xf0);
		b = (byte)((Tab[0] & 0xf) << 4);
		break;
	}
	SaveByte[Offset + 0] = b;
	SaveByte[Offset + 1] = g;
	SaveByte[Offset + 2] = r;
	SaveByte[Offset + 3] = a;
}

NPK_M::NPK_M()
{
}

void NPK_M::init()
{
	WIN32_FIND_DATAA lpdata;
	DWORD read;

	HANDLE hFindFile = FindFirstFileA("ImagePacks2\\*.npk", &lpdata);
	do {
		//拼接完整路径
		char cat[256] = "ImagePacks2\\";
		strcat(cat, lpdata.cFileName);

		ReadNpk Fs;
		Fs.open(cat, std::ios::in | std::ios::binary);

		if (Fs)
		{
			std::string Header = Fs.ReadString();
			//如果是NPK
			if (Header._Equal("NeoplePack_Bill"))
			{
				//读取img数量
				int ImageCount = Fs.ReadInt();
				//读取头
				NpkInfo* ImgList = new NpkInfo[ImageCount];
				for (size_t i = 0; i < ImageCount; i++)
				{
					ImgList[i].Offset = Fs.ReadInt();
					ImgList[i].Length = Fs.ReadInt();
					ImgList[i].Path = Fs.ReadInfo();
				}
				for (int i = 0; i < ImageCount; i++)
				{
					IMG img;

					img.imgOffset = ImgList[i].Offset;
					img.imgSize = ImgList[i].Length;
					img.img_index = i;
					img.lpBelongsFile = lpdata.cFileName;
					img.lpImgName = ImgList[i].Path;
					img.lp_lplist = NULL;
					img.png_sum = 0;

					map_npk.insert(make_pair(img.lpImgName, img));
				}
				//销毁
				delete[]ImgList;
			}
		}
		Fs.close();
	} while (FindNextFileA(hFindFile, &lpdata));
	FindClose(hFindFile);



	ReadNpkTable("sprite/interface2/event/chn_event_2016/160927_joustmatches/knight0.img");
	return;
}

LPDWORD NPK_M::LoadImgToMem(IMG* p)
{
	//拼接NPK名称
	char dirname[256] = "ImagePacks2\\";
	strcat(dirname, p->lpBelongsFile.c_str());

	ReadNpk Fs;
	Fs.open(dirname, std::ios::in | std::ios::binary);

	if (Fs)
	{
		Fs.seekg(p->imgOffset);
		std::string Flag = Fs.ReadString();
		if (Flag._Equal("Neople Img File"))
		{
			//索引表大小
			long TableLength = Fs.ReadLong();
			//img 版本 4字节
			int ver = Fs.ReadInt();
			//img 帧数
			int IndexCount = Fs.ReadInt();
			Npk_PngMutex.lock();
			//图片数量赋值
			p->png_sum = IndexCount;
			Npk_PngMutex.unlock();

			//new出 Png数量的 结构体
			ImgInfo* PngList = new ImgInfo[IndexCount];

			for (size_t i = 0; i < IndexCount; i++)
			{
				PngList[i].Type = Fs.ReadInt();
				if (PngList[i].Type == 17)
				{
					//引用贴图
					int frbuf = Fs.ReadInt();

					continue;
				}
				//压缩类型
				PngList[i].CmpType = Fs.ReadInt();
				//宽度
				PngList[i].Width = Fs.ReadInt();
				//高度
				PngList[i].Height = Fs.ReadInt();
				//大小
				PngList[i].Size = Fs.ReadInt();
				//Xpos
				PngList[i].Xpos = Fs.ReadInt();
				//Ypos
				PngList[i].Ypos = Fs.ReadInt();
				//帧域X
				PngList[i].FrameXpos = Fs.ReadInt();
				//帧域Y
				PngList[i].FrameYpos = Fs.ReadInt();
				//计算偏移
				if (i == 0)PngList[i].Offset = 0 + p->imgOffset + TableLength + 32;
				else PngList[i].Offset = PngList[i - 1].Offset + PngList[i - 1].Size;

			}

			for (size_t i = 0; i < IndexCount; i++)
			{
				Fs.seekg(PngList[i].Offset);
				BYTE* PngData = Fs.ReadCustomSize(PngList[i].Size);
				int DeSize = PngList[i].Width * PngList[i].Height * 4;
				BYTE* bByte = new BYTE[DeSize];
				ULONG RealSize = DeSize;
				int a = uncompress(bByte, &RealSize, PngData, (ULONG)PngList[i].Size);
				delete[]PngData;


				if (PngList[i].Type != 16)
				{
					int PngByteSize = DeSize * 2;
					PngList[i].PNGdata = new BYTE[PngByteSize];

					for (int e = 0; e < PngByteSize; e += 4)
					{
						BYTE NeedData[2];
						memset(NeedData, 0, 2);
						memcpy(NeedData, bByte + (e / 4) * 2, 2);
						ReadColor(NeedData, PngList[i].Type, PngList[i].PNGdata, e);
					}

					delete[]bByte;
				}
				else {
					PngList[i].PNGdata = bByte;
				}
			}

			Npk_PngMutex.lock();
			p->lp_lplist = PngList;
			Npk_PngMutex.unlock();
		}
	}
	Fs.close();

	return 0;
}

IMG* NPK_M::ReadNpkTable(const std::string imgpath)
{
	std::cout << imgpath << std::endl;
	IMG* img = NULL;

	Npk_ImgMutex.lock();
	std::map<std::string, IMG>::iterator itr;
	itr = map_npk.find(imgpath);
	if (itr == map_npk.end()) {
		std::string mes = "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!调用了不存在的Img : " + imgpath;
		//MessageBoxA(0, mes.c_str(), 0, 0);
		img = &map_npk["sprite/interface/base.img"];
	}
	else {
		img = &itr->second;
	}
	Npk_ImgMutex.unlock();

	//如果图片数组不存在 或者 图片数据不存在都要重读
	if (!img->lp_lplist || !img->lp_lplist->PNGdata) {
		LoadImgToMem(img);
	}
	return img;
}

void NPK_M::ReleaseNpkTable(IMG* p)
{
	for (int i = 0; i < p->png_sum; i++) {
		if (p->lp_lplist[i].PNGdata) {
			delete p->lp_lplist[i].PNGdata;
			p->lp_lplist[i].PNGdata = 0;
		}
		else {
			int a = 0;
		}
	}
	//delete[] p->lp_lplist;

	//p->lp_lplist = NULL;
}

int Translate24Bto32B_cpp(char* des, char* src, int num)
{
	for (int i = 0; i < (num / 4); i++) {
		unsigned short aword = *(unsigned short*)src;
		unsigned short A = aword >> 12;
		unsigned short R = 15 & aword >> 8;
		unsigned short G = 15 & aword >> 4;
		unsigned short B = 15 & aword >> 0;

		A = (A * 255) / 15;
		B = (B * 255) / 15;
		G = (G * 255) / 15;
		R = (R * 255) / 15;

		unsigned int aDword = 0;
		aDword |= A;
		aDword <<= 8;
		aDword |= R;
		aDword <<= 8;
		aDword |= G;
		aDword <<= 8;
		aDword |= B;

		*(unsigned int*)des = aDword;

		src += 2;
		des += 4;
	}
	return 0;
}

int Translate16Bto32B_cpp(char* des, char* src, int num)
{
	for (int i = 0; i < (num / 4); i++) {
		unsigned short aword = *(unsigned short*)src;
		unsigned short A = aword >> 15;
		unsigned short R = 31 & aword >> 10;
		unsigned short G = 31 & aword >> 5;
		unsigned short B = 31 & aword >> 0;

		A = A * 255;
		B = (B * 255) / 31;
		G = (G * 255) / 31;
		R = (R * 255) / 31;

		unsigned int aDword = 0;
		aDword |= A;
		aDword <<= 8;
		aDword |= R;
		aDword <<= 8;
		aDword |= G;
		aDword <<= 8;
		aDword |= B;

		*(unsigned int*)des = aDword;

		src += 2;
		des += 4;
	}
	return 0;
}

NPK_M::~NPK_M()
{
	map_npk.clear();
}