#include <shinobi.h>
#include <kamui2.h>
#include <km2util.h>
#include <string.h>
#include "dispstrex.h"
#include "command.h"
#include "filename.h"
#include "filesys.h"
#include "ctype.h"

const char ATR_ON[]  = "EDARPM";
const char ATR_OFF[] = "------";
const DWORD ATR_COL[] = {
	0xffffffff,
	0xff0000ff,
	0xff00ffff,
	0xffff0000,
	0xff00ff00,
	0xffffff00,
	0xffff00ff,
};

static void *pMem = NULL;

static void ToUpperStr(char *pStr);
/*----------------------------------------------------------------------------------*/
void ToUpperStr(char *pStr)
{
	while(*pStr) {
		*pStr = toupper(*pStr);
		pStr++;
	}
}
/*----------------------------------------------------------------------------------*/
void CdCommand(int argc, char *argv[])
{
	if (gdFsChangeDir( argv[1] )!=GDD_ERR_OK) {
		PRINTOUT(("Can not change directory.\n"));
		return;
	}
}
/*----------------------------------------------------------------------------------*/
void LsCommand(int argc, char *argv[])
{
	int i,num,size,mode;
	char atr[8];
	char dir[256];
	char file[32];
	char ext[8];

	char w0[32];
	char w1[32];

	GDFS_DIRREC pDIR;
	GDFS_DIRREC_ENT *pENT;

	if (argc>1 && argv[1][0]!='-') {
		fuGetFileName( argv[1], w0 );
		fuGetExtName ( argv[1], w1 );
	} else {
		strcpy( w0, "*" );
		strcpy( w1, "*" );
	}

	ToUpperStr(w0);
	ToUpperStr(w1);

	pDIR = syMalloc(0x10000);
	if (pDIR==NULL) {
		PRINTOUT(("Not enough memory.\n"));
		return;
	}

	i = gdFsLoadDir( ".", pDIR );
	if (i!=GDD_ERR_OK) {
		PRINTOUT(("Can not access GD.[%d]\n" ,i ));
		return;
	}

	if (strcmp( argv[argc-1], "-w" )==0) mode=1; else mode=0;

	num  = 0;
	size = 0;
	pENT = &pDIR->dirrec_tbl[0];

	for(i=0; i<pDIR->dir_num; i++) {
		DWORD col = ATR_COL[0];

		strcpy( atr, ATR_OFF );
		if (pENT->flag & GDD_FF_EXISTENCE      ) { atr[0]=ATR_ON[0]; col = ATR_COL[1]; }
		if (pENT->flag & GDD_FF_DIRECTORY      ) { atr[1]=ATR_ON[1]; col = ATR_COL[2]; }
		if (pENT->flag & GDD_FF_ASSOCIATED_FILE) { atr[2]=ATR_ON[2]; col = ATR_COL[3]; }
		if (pENT->flag & GDD_FF_RECORD         ) { atr[3]=ATR_ON[3]; col = ATR_COL[4]; }
		if (pENT->flag & GDD_FF_PROTECTION     ) { atr[4]=ATR_ON[4]; col = ATR_COL[5]; }
		if (pENT->flag & GDD_FF_MULTI_EXTENT   ) { atr[5]=ATR_ON[5]; col = ATR_COL[6]; }

		fuGetFileName( pENT->fname, file );
		fuGetExtName ( pENT->fname, ext  );

		if (ext[0]=='\0') {
			if (strcmp(file, ".")==0) strcpy(file, "..");
			if (strcmp(file,  "")==0) strcpy(file, ".");
		}

		if ((fuCheckStr(file, w0))&&(fuCheckStr(ext, w1))) {
			txt_SetColor( ((col>>16)&0xff)/255.f,((col>>8)&0xff)/255.f,(col&0xff)/255.f );

			if (mode) {
				PRINTOUT(("%14s.%-3s", file,ext));
				if ((num+1)%2==0) {
					PRINTOUT(("\n"));
				} else {
					PRINTOUT((" "));
				}
			} else {
				if (ext[0]=='\0') {
					PRINTOUT(("%6s %16s     %8d \n", atr, file, pENT->fsize));
				} else {
					PRINTOUT(("%6s %16s.%-3s %8d \n", atr, file,ext, pENT->fsize));
				}
			}
			size += pENT->fsize;
			num++;
		}
		pENT++;
	}

	txt_SetColor( 1.f, 1.f, 1.f );
	PRINTOUT(("\n %d file(s)  total %d byte\n\n", num,size));

	syFree( pDIR );
}
/*----------------------------------------------------------------------------------*/
void ReCommand(int argc, char *argv[])
{
	GDFS sys;
	volatile int i;

	while(1) {
		while(gdFsReqDrvStat()!=GDD_ERR_OK);
		while(gdFsGetDrvStat()==GDD_STAT_BUSY);

		sys = gdFsGetSysHn();
		for(i=0; i<10000000; i++);

		switch (gdFsGetErrStat(sys)) {
		case GDD_ERR_OK:
			PRINTOUT(("Ok.\n"));
			return;
		case GDD_ERR_TRAYOPEND:
			PRINTOUT(("Tray Open.\n"));
			return;
		case GDD_ERR_UNITATTENT:
			while(1) {
				int r = syBtCheckDisc();
				if (r>0) {
					PRINTOUT(("Not Found GDROM.\n"));
					return;
				}
				if (r==0) {
					PRINTOUT(("Fount GDROM.\n"));
					return;
				}
				for(i=0; i<100000; i++);
			}
			break;
		default:
			PRINTOUT(("Fatal Error.\n"));
			return;
		}
	}
}
/*----------------------------------------------------------------------------------*/
void LdCommand(int argc, char *argv[])
{
	int Size;
	if (argc==1) {
		PRINTOUT(("ld <filename>\n"));
		return;
	}
	Size = fsGetFileSize( argv[1] );
	if (Size==0) {
		PRINTOUT(("%s is not found.\n", argv[1]));
		return;
	}

	if (pMem) {
		syFree( pMem );
		pMem = NULL;
	}

	pMem = syMalloc( Size );
	if (pMem==NULL) {
		PRINTOUT(("Not enough memory.\n"));
		return;
	}
	fsLoadFile( argv[1], pMem, Size );

	PRINTOUT(("ADRS = $%8x [$%x].\n", pMem, Size));
}
/*----------------------------------------------------------------------------------*/
void InitLsCommand(void)
{
	RegisterCommand(LsCommand, NULL, NULL, "ls", PROCESSTYPE_WO_DRAW);
	RegisterCommand(CdCommand, NULL, NULL, "cd", PROCESSTYPE_WO_DRAW);
	RegisterCommand(ReCommand, NULL, NULL, "re", PROCESSTYPE_WO_DRAW);
}
/*----------------------------------------------------------------------------------*/