
/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/

	FILE	: DataLoad.cpp

+ ------ Explanation of file --------------------------------------------------------------------------

	各データのロード

+ _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */

#include <setjmp.h>
#include <assert.h>

#include "include\png.h"
#include "include\jpeglib.h"

#include "Common.h"

#include "Renderer.h"
#include "Button.h"
#include "Field.h"
#include "CardData.h"

#include "DataLoad.h"

//#define CARDFILLING		// 著作権どうたらこうたら用

struct my_error_mgr {
	struct jpeg_error_mgr pub;	/* "public" fields */
	jmp_buf setjmp_buffer;	/* for return to caller */
};
typedef struct my_error_mgr * my_error_ptr;
typedef struct _MEMPNG {
	unsigned char *buf;
	UINT32 offset;
} MEMPNG;

static void *commonalpha = NULL;
static DWORD cardsize = 0;

METHODDEF(void) my_error_exit(j_common_ptr cinfo){
	my_error_ptr myerr = (my_error_ptr) cinfo->err;
	longjmp(myerr->setjmp_buffer, 1);
}
int jpegparser(void **out, void *in, UINT32 *width, UINT32 *height, UINT32 size, UINT32 *outsize, UINT32 *pitch){
	unsigned char *decomp = NULL;
	unsigned char **ptrtable;
	struct jpeg_decompress_struct jdecomp;
	struct my_error_mgr jerr;
	DWORD decompsize;
	int pixelsize;
	unsigned int i;

	ZeroMemory(&jdecomp, sizeof(jpeg_decompress_struct));
	ZeroMemory(&jerr, sizeof(my_error_mgr));

	jdecomp.err = jpeg_std_error(&jerr.pub);
	jerr.pub.error_exit = my_error_exit;
	if(setjmp(jerr.setjmp_buffer)) {
		jpeg_destroy_decompress(&jdecomp);
		return -1;
	}

	jpeg_create_decompress(&jdecomp);
	jpeg_mem_src(&jdecomp, (unsigned char *)in, size);
	jpeg_read_header(&jdecomp, TRUE);
	jdecomp.out_color_space = JCS_EXT_BGRA;
	jpeg_start_decompress(&jdecomp);

	pixelsize = jdecomp.output_components;
	*width = (UINT32)jdecomp.image_width;
	*height = (UINT32)jdecomp.image_height;
	*pitch = *width * pixelsize;
	decompsize = *height * *pitch;
	*outsize = decompsize;

	decomp = (unsigned char *)HeapAlloc(GetProcessHeap(), 0, decompsize);
	ptrtable = (unsigned char **)HeapAlloc(GetProcessHeap(), 0, jdecomp.output_height * sizeof(unsigned char *));

	for(i = 0; i < *height; i++)
		ptrtable[i] = decomp + i * *pitch;

	while(jdecomp.output_scanline<jdecomp.output_height)
		jpeg_read_scanlines(&jdecomp, &ptrtable[jdecomp.output_scanline], jdecomp.output_height - jdecomp.output_scanline);

	jpeg_finish_decompress(&jdecomp);
	jpeg_destroy_decompress(&jdecomp);

	HeapFree(GetProcessHeap(), 0, ptrtable);
	*out = decomp;

	return 0;
}
void my_png_read_data(png_structp png_ptr, png_bytep data, png_size_t length){
	MEMPNG *p = (MEMPNG *)png_get_io_ptr(png_ptr);
	memcpy(data, p->buf + p->offset, length);
	p->offset += length;
}
int pngparser(void **out, void *in, UINT32 *width, UINT32 *height, UINT32 size, UINT32 *outsize, UINT32 *pitch){
	int ret;
	unsigned int i;
	png_structp png_ptr = NULL;
	png_infop info_ptr = NULL;

	MEMPNG mempng;
	png_bytep *rowptrs;
	int bitDepth = 0;
	int colorType = -1;
	UINT32 nsize;

	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if(png_ptr == NULL)
		return -1;

	mempng.buf = (unsigned char *)in;
	mempng.offset = 0;

	info_ptr = png_create_info_struct(png_ptr);

	if(setjmp(png_jmpbuf(png_ptr))){
		return -1;
	}

	if(info_ptr == NULL)	{
		png_destroy_read_struct(&png_ptr, NULL, NULL);
		return -1;
	}

	png_set_read_fn(png_ptr, &mempng, my_png_read_data);

	png_read_info(png_ptr, info_ptr);

	ret = png_get_IHDR(png_ptr, info_ptr, width, height, &bitDepth, &colorType, NULL, NULL, NULL);

	png_set_bgr(png_ptr);
	if(colorType == PNG_COLOR_TYPE_RGB)
		png_set_add_alpha(png_ptr, 255, PNG_FILLER_AFTER);

	png_read_update_info(png_ptr, info_ptr);

	*pitch = png_get_rowbytes(png_ptr,info_ptr);
	nsize = *height * *pitch;
	rowptrs = (png_bytep *)HeapAlloc(GetProcessHeap(), 0, *height * sizeof(void *));
	*out = HeapAlloc(GetProcessHeap(), 0, nsize);
	*outsize = nsize;

	for(i = 0; i < *height; i++){
		rowptrs[i] = (png_bytep)((UINT32)*out + i * *pitch);
	}

	png_read_image(png_ptr, rowptrs);
	HeapFree(GetProcessHeap(), 0, rowptrs);

	png_destroy_info_struct(png_ptr, &info_ptr);
	png_destroy_read_struct(&png_ptr, NULL, NULL);

	return 0;
}

#if 0
//! デッキファイル取得
int GetDeckList(VecStr* pDeck)
{
	WIN32_FIND_DATA win32fd;
	HANDLE hFind;
	string str;
	int iRet = 0;

	hFind = FindFirstFile("Deck\\*", &win32fd);
	do{
		if(strstr(win32fd.cFileName, ".deck")){
			str = "Deck\\";
			str += win32fd.cFileName;
			pDeck->push_back(str);
			iRet++;
		}
	}while(FindNextFile(hFind, &win32fd));

	return(iRet);
}
//! デッキ読み込み
bool GetDeckCard(const char* file, int* pDeck)
{
#define READNUM(num)		{memcpy_s(&num, sizeof(int), &deckData[index], sizeof(int)); index += sizeof(int);}
#define READSTR(str)		{str = &deckData[index]; index += strlen(&deckData[index])+1;}
	FILE*	fp;
	char*	deckData;
	int		fileStart;
	int		fileSize;
	int		index = 0;
	char*	pStr;
	int		num;

	fopen_s(&fp, file, "rb");
	if(!fp){
		return(false);
	}

	// サイズ取得
	fileStart = fseek(fp, 0, SEEK_END);
	fileSize = ftell(fp);
	fseek(fp, fileStart, SEEK_SET);

	// バッファに読み込み
	deckData = (char*)malloc(fileSize);
	fread_s(deckData, fileSize, fileSize, 1, fp);
	fclose(fp);

	// バッファから分解
	for(int i = 0; i < DECK_MAX; i++){
		READSTR(pStr);	// シリーズ名
		READNUM(num);	// シリーズ番号
		// シリーズ名toカード番号
		for(int j = 0; j < SERIES_MAX; j++){
			pDeck[i] = CNtSN(MDW(SStSN(pStr), num));
			break;
		}
	}

	return(true);
#undef READNUM
#undef READSTR
}
//! デッキが正規かチェック
int CheckDeck(CARD_INFO* card)
{
	CARD_INFO* cpy = card;
	int iRet = DECK_CHECK_OK;
	int cnt = 0;

	// デッキ枚数チェック
	for(int i = 0; i < DECK_MAX; i++){
		if(card->serNo == -1){
			iRet |= DECK_CHECK_NOT_DATA;
			break;
		}
		card++;
	}
	card = cpy;

	// 同名チェック
	int dm[DECK_MAX][2];
	for(int i = 0; i < DECK_MAX; i++){
		dm[i][0] = -1;
		dm[i][1] = 0;
	}
	for(int i = 0; i < DECK_MAX; i++){
		for(int j = 0; j < DECK_MAX; j++){
			if(dm[j][0] == -1){
				dm[j][0] = card->serNo;
				dm[j][1]++;
				break;
			}
			else if(dm[j][0] == card->serNo){
				dm[j][1]++;
				break;
			}
		}
		card++;
	}
	for(int i = 0; i < DECK_MAX; i++){
		if(dm[i][1] > 4){
			iRet |= DECK_CHECK_SAME_OVER;
			break;
		}
	}
	card = cpy;

	// Lv0チェック
	for(int i = 0; i < DECK_MAX; i++){
		if(card->level == 0 && card->type == TYPE_PG){
			cnt++;
		}
		card++;
	}
	if(cnt < 4){
		iRet |= DECK_CHECK_LV0_UNDER;
	}
	else if(cnt > 4){
		iRet |= DECK_CHECK_LV0_OVER;
	}
	card = cpy;

	// フレームチェック
	cnt = 0;
	for(int i = 0; i < DECK_MAX; i++){
		if(card->level > 0 && card->frame != FRAME_NON){
			cnt++;
		}
		card++;
	}
	if(cnt < 16){
		iRet |= DECK_CHECK_FRAME_UNDER;
	}
	else if(cnt > 16){
		iRet |= DECK_CHECK_FRAME_OVER;
	}
	card = cpy;

	// キーパーチェック
	Card cd;
	ZeroMemory(&cd, sizeof(cd));
	cnt = 0;
	for(int i = 0; i < DECK_MAX; i++){
		cd.m_ci = *card;
//		if(skill.invoke(&cd, 0, SKILL_CODE_GET_CONTENT) == SKILL_RET_KEEPER){
		if(0){
			cnt++;
		}
		card++;
	}
	if(cnt > 4){
		iRet |= DECK_CHECK_KEEPER_OVER;
	}
	card = cpy;

	// エースチェック
	int acnt[6] = { 0 };
	for(int i = 0; i < DECK_MAX; i++){
		cd.m_ci = *card;
//		if(skill.invoke(&cd, 0, SKILL_CODE_GET_CONTENT) == SKILL_RET_ACE){
		if(0){
			acnt[card->level]++;
		}
		card++;
	}
	for(int i = 0; i < 6; i++){
		if(acnt[i] > 4){
			iRet |= DECK_CHECK_ACE_OVER;
			break;
		}
	}
	card = cpy;

	// 禁止チェック
	for(int i = 0; i < DECK_MAX; i++){
		for(int j = 0; j < PROHIBITION_MAX; j++){
			if(card->serNo == gCardProhibition[j]){
				iRet |= DECK_CHECK_PROHIBITION;
				i = DECK_MAX;
				break;
			}
		}
		card++;
	}
	card = cpy;

	// 制限チェック
	int rest[RESTRICTION_MAX] = { 0 };
	for(int i = 0; i < DECK_MAX; i++){
		for(int j = 0; j < RESTRICTION_MAX; j++){
			if(card->serNo == gCardRestriction[j].serNo){
				rest[j]++;
				break;
			}
		}
		card++;
	}
	for(int i = 0; i < RESTRICTION_MAX; i++){
		if(rest[i] > gCardRestriction[i].num){
			iRet |= DECK_CHECK_RESTRICTION;
			break;
		}
	}
	card = cpy;

	// コンビチェック
	int combi[COMBINATION_MAX][2] = { 0 };
	for(int i = 0; i < DECK_MAX; i++){
		for(int j = 0; j < COMBINATION_MAX; j++){
			for(int k = 0; k < 2; k++){
				if(card->serNo == gCardCombination[j][k]){
					combi[j][k]++;
				}
			}
		}
		card++;
	}
	for(int i = 0; i < COMBINATION_MAX; i++){
		if(combi[i][0] > 0 && combi[i][1] > 0){
			iRet |= DECK_CHECK_COMBINATION;
			break;
		}
	}
	card = cpy;

	return(iRet);
}
//! チェック表示
void CheckPrint(int check)
{
	char* str[] = {
		"デッキが54枚未満です",
		"同名カードが4枚超過です",
		"Lv0が4枚未満です",
		"Lv0が4枚超過です",
		"フレームが16枚未満です",
		"フレームが16枚超過です",
		"キーパーが4枚超過です",
		"エースが4枚超過です",
		"禁止カードが含まれています",
		"制限カードが制限枚数超過です",
		"コンビネーション制限カードが含まれています"
	};

	if(check == 0){
		printf("このデッキは使用可能です\n");
	}
	else{
		for(int i = 0; i < SIZEARY(str); i++){
			if((check & (1 << i))){
				printf("error:%s\n", str[i]);
			}
		}
		printf("error:このデッキは使用不可です\n");
	}
}
#endif

