/*!
@file map_chip.c
@file マップチップのデータ構造と処理（C言語版）
@note
*/
#define DKUTIL_GRAPHICS_2D_MAPCHIP_C

#include <dkutil/graphics/2d/map_chip.h>
#include <dkutil_c/dkcStream.h>



DKC_GRAPHICS_2D_MAP_CHIP_STATE *WINAPI dkcAllocGraphics2DMapChip(){
	DKC_GRAPHICS_2D_MAP_CHIP_STATE *p = //dkcAllocateはメモリ領域を全部０で初期化する。
		dkcAllocate(sizeof(DKC_GRAPHICS_2D_MAP_CHIP_STATE));

	//error check
	dkcmNOT_ASSERT(sizeof(p->header.height) != 4);
	
	//uninitialized...
	p->flag = FALSE;
	return p;
}

int WINAPI dkcFreeGraphics2DMapChip(DKC_GRAPHICS_2D_MAP_CHIP_STATE **pp){
	
	if(NULL==pp || NULL==(*pp) ){
		return edk_FAILED;
	}
	/*if( (*pp)->memory ){
		dkcFree( &((*pp)->memory) );
	}*/
	Unload2DMapData((*pp));
	return dkcFree((void *)pp);
}

static BOOL Load2DMapHeader(DKC_STREAM *ps,DKC_GRAPHICS_2D_MAP_CHIP_HEADER *pd){
	size_t t;
	size_t rs;
	size_t i;
	
	//width
	dkcStreamRead32(ps,&t,sizeof(t),&rs);
	if(rs != sizeof(t)){
		return FALSE;
	}
	pd->width = t;
	//height
	dkcStreamRead32(ps,&t,sizeof(t),&rs);
	if(rs != sizeof(t)){
		return FALSE;
	}
	pd->height = t;

	//hash_value
	dkcStreamRead(ps,&(pd->hash_value),sizeof(pd->hash_value),&rs);
	if(rs!=sizeof(pd->hash_value)){
		return FALSE;
	}

	//offset
	dkcStreamRead(ps,&(pd->offset),sizeof(BYTE),&rs);
	if(rs!=sizeof(BYTE)){
		return FALSE;
	}
	return TRUE;
}

static BOOL Load2DMapData(DKC_STREAM *ps,
									 DKC_GRAPHICS_2D_MAP_CHIP_STATE *pd,
									 DKC_GRAPHICS_2D_MAP_CHIP_HEADER *header)
{

	size_t map_size = header->offset * header->width * header->height;
	int r;
	size_t readsize;

	//メモリ確保
	pd->memory = dkcAllocate(map_size);
	if(NULL==pd->memory){
		return FALSE;
	}
	pd->size = map_size;
	
	//読みこみ処理を分岐 (ここで指定した通り読みこまない時がある　これは私のライブラリの欠陥。いずれ直す･･･
	switch(header->offset){
	case 1:
		r = dkcStreamRead(ps,pd->memory,map_size,&readsize);
		break;
	case 2:
		r = dkcStreamRead16(ps,pd->memory,map_size,&readsize);
		break;
	case 4:
		r = dkcStreamRead32(ps,pd->memory,map_size,&readsize);
		break;
	case 8:
		r = dkcStreamRead64(ps,pd->memory,map_size,&readsize);
		break;
	default:
		goto Error;
	}
	if(DKUTIL_FAILD(r) || readsize != map_size){
		goto Error;
	}
	return TRUE;
Error:
	Unload2DMapData(pd);
	return FALSE;
}



static BOOL Save2DMapHeader(DKC_STREAM *ps,const DKC_GRAPHICS_2D_MAP_CHIP_HEADER *pd){
	int r;
	dkcStreamSeek(ps,0,edkcStreamSeekSet);
	//width
	r = dkcStreamWrite32(ps,&(pd->width),sizeof(pd->width));
	if(DKUTIL_FAILED(r)){
		return FALSE;
	}
	//height
	r = dkcStreamWrite32(ps,&(pd->width),sizeof(pd->height));
	if(DKUTIL_FAILED(r)){
		return FALSE;
	}
	//hash_value
	r = dkcStreamWrite(ps,&(pd->hash_value),sizeof(pd->hash_value));
	if(DKUTIL_FAILED(r)){
		return FALSE;
	}
	//offset
	r = dkcStreamWrite(ps,&(pd->offset),sizeof(BYTE));
	if(DKUTIL_FAILED(r)){
		return FALSE;
	}
	return TRUE;

}
static BOOL Save2DMapData(DKC_STREAM *ps,
													DKC_GRAPHICS_2D_MAP_CHIP_STATE *pd,
													DKC_GRAPHICS_2D_MAP_CHIP_HEADER *header)
{

}

static int Unload2DMapData(DKC_GRAPHICS_2D_MAP_CHIP_STATE *pd){
	return dkcFree(&(pd->memory));
}


int WINAPI dkcLoadGraphics2DMapChip(
	DKC_GRAPHICS_2D_MAP_CHIP_STATE *p,const char *filename,
	const BYTE *dustbin,size_t dustbin_size)
{
	int r = edk_FAILED;
	DKC_SHA1 *psha = NULL;
	DKC_STREAM *ps;
	BYTE hash[SHA1_BIN_BUFFER_SIZE];
	DKC_GRAPHICS_2D_MAP_CHIP_HEADER h;
	
	ps = dkcAllocStreamEncouragementFileType(
		filename,
		"rb",// read binary
		TRUE
	);



	if(FALSE==Load2DMapHeader(ps,&h)){
		goto End;
	}
	if(FALSE==Load2DMapData(ps,p,&h)){
		goto End;
	}
	/*
	SHA1の算出の仕方
	DKC_GRAPHICS_2D_MAP_CHIP_HEADERの width hegiht offset マップチップ分
	によって算出する
	*/
	{
		psha = dkcAllocSHA1();
		if(NULL==psha){
			goto End;
		}

		dkcSHA1Load(psha,dustbin,dustbin_size);
		dkcSHA1Load(psha,&(h.width),sizeof(h.width));
		dkcSHA1Load(psha,&(h.height),sizeof(h.height));
		dkcSHA1Load(psha,&(h.offset),sizeof(h.offset));
		dkcSHA1Load(psha,p->memory,p->size);
		dkcSHA1FinalDigest(psha,hash,sizeof(hash));
		dkcSHA1Load(psha,dustbin,dustbin_size);


		if(DKUTIL_FAILED(dkc_memcmp(hash,sizeof(hash),h.hash_value,sizeof(h.hash_value))))
		{//違うようなのでサヨウナラ･･･
			goto End;
			r = edk_FileCheated_Change;
		}

	}

	//update
	r = edk_SUCCEEDED;
	p->flag = TRUE;
End:
	dkcFreeSHA1(&psha);
	dkcFreeStream(&ps);
	return r;


}




int WINAPI dkcSaveGraphics2DMapChip(
	const char *filename,
	size_t width,size_t height,BYTE offset,const void *memory,size_t memory_size,
	const BYTE *dustbin,size_t dustbin_size
	)
{
	DKC_STREAM *ps = NULL;
	DKC_GRAPHICS_2D_MAP_CHIP_HEADER h;
	DKC_SHA1* psha = NULL;
	int r = edk_FAILED;
	//BYTE hash[SHA1_BIN_BUFFER_SIZE];

	//filter


	if(memory_size != width * height * offset)
	{//ちょっと引数が違うナァ
		return edk_ArgumentException;
	}


	//initialize
	ps = dkcAllocStreamEncouragementFileType(
		filename,
		"wb",// write binary
		TRUE
	);


	if(NULL==ps){
		return edk_OutOfMemory;
	}

	psha = dkcAllocSHA1();

	if(NULL==psha){
		goto End;
	}

	//set data
	h.width = width;
	h.height = height;
	h.offset = offset;

	//generate sha
	dkcSHA1Load(psha,dustbin,dustbin_size);
	dkcSHA1Load(psha,&(h.width),sizeof(h.width));
	dkcSHA1Load(psha,&(h.height),sizeof(h.height));
	dkcSHA1Load(psha,&(h.offset),sizeof(h.offset));
	dkcSHA1Load(psha,memory,memory_size);
	dkcSHA1FinalDigest(psha,&(h.hash_value),sizeof(h.hash_value));
	dkcSHA1Load(psha,dustbin,dustbin_size);


	//とりあえず、ヘッダ分をシークしておく
	//dkcStreamSeek(ps,sizeof(	DKC_GRAPHICS_2D_MAP_CHIP_HEADER),edkcStreamSeekSet);
	
	//ファイルの先頭にしてセーブしておく。
	Save2DMapHeader(ps,&h);

	


	//読みこみ処理を分岐 (ここで指定した通り読みこまない時がある　これは私のライブラリの欠陥。いずれ直す･･･
	switch(offset){
	case 1:
		r = dkcStreamWrite(ps,memory,memory_size);
		break;
	case 2:
		r = dkcStreamWrite16(ps,memory,memory_size);
		break;
	case 4:
		r = dkcStreamWrite32(ps,memory,memory_size);
		break;
	case 8:
		r = dkcStreamWrite64(ps,memory,memory_size);
		break;
	default:
		r =  edk_ArgumentException;
		goto End;
	}

	if(DKUTIL_FAILD(r)){
		goto End;
	}
	r = edk_SUCCEEDED;
End:
	dkcFreeSHA1(&psha);
	dkcFreeStream(&ps);
	return r;

	


}


DKC_GRAPHICS_2D_MAP_CHIP_HEADER *WINAPI dkcGraphics2DMapChipGetHeaderPointer(
	DKC_GRAPHICS_2D_MAP_CHIP_STATE *p
	){
	if(NULL==p || FALSE==p->flag){
		return NULL;
	}
	return &(p->header);
}

BOOL WINAPI dkcGraphics2DMapChipGetChipArrayInfomation(
	DKC_GRAPHICS_2D_MAP_CHIP_STATE *p,void **memory_ptr,size_t *memory_size,BYTE *offset
	)
{
	if(NULL==p || FALSE==p->flag){
		return FALSE;
	}
	*memory_ptr = p->memory;
	*memory_size = p->size;
	*offset = p->header.offset;
	return TRUE;
}


