#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winb.h>
#include <te.h>
#include <fntb.h>
#include <gui.h>
#include <egb.h>
#include <guidbg.h>

//#include <eintm.h>
#include <KH.h>
#include <dlib.h>
#include <mos.h>

//#define DEBUG

char	*guiEgbPtr ;			/*	EGB のワークアドレス	*/

int	dialogID = -1 ;
int	iconID = -1 ;

void	userIdleTask(void);		//アイドルタスク
void	setDirectory(void);		//次の進行方向と距離を決める
void	toBackGround(void);		//バックグラウンドにする
void	getScreenSize(void);	//画面の大きさを取得

unsigned char	g_Count;	//ごきの動く数(=0:停止中 =1:停止開始 >1:逃走中)
int				g_X,g_Y;	//ごきの位置
unsigned char	g_Angle;	//ごきの向き(0〜7)
FRAME			screen;		//画面の大きさ
FRAME			gfr;
EVENT			gev;
int				myID;		//自分のアプリID
int				shellID;	//シェルのアプリID
int				xx[8] = {  0,  9, 12,  9,  0,  -9, -12,  -9};
int				yy[8] = {-12, -9,  0,  9, 12,   9,   0,  -9};

int userFunc(apliId, messId, info, data)
int	apliId;
int	messId;
int	info;
int	data;
{
	register int	ret;

	ret = ILLEGAL_FUNCTION;

	switch(messId)
	{
		case	GM_QUIT :
		case	GM_PURGE :
			MMI_SetHaltFlag(TRUE);
			ret = NOERR ;
			break;

		case	GM_WAKE :
			toBackGround();			//バックグラウンドにする
			break;

		case	GM_POSTSCRCHG :
			getScreenSize();		//画面の大きさを取得
			break;

		default:
			break;
	}

	return(ret);
}

void main()
{
	static MMICTRL mmi ={
				SCREEN16|SCREENIGNORE,		// ページ0側解像度
				SCREENUNUSED,				// ページ1側解像度
				0, 							// 書き込みページ
				SCREENAVAILABLE, 			// 表示ページ
				0, 							// 表示プライオリティ
				SCREENAVAILABLE,			// 色数
				SCREENEXPAND, 				// VRAMの横の長さ
				0, 							// メモリ領域の大きさ
				NULL, 						// メモリ領域のアドレス
				0, 							// ユーザ領域の大きさ
				NULL, 						// ユーザ領域のアドレス
				0, 0, 						// 画面枠	lupx,lupy
				0, 0,						//			rdwx,rdwy
				-16384, -16384,				// 移動枠	lupx,lupy
				16383, 16383,				//			rdwx,rdwy
				15, 						// 白色
				8,  						// 黒色
				7,  						// 灰色
				6	 						// 反転色
	};

	extern int APL_init() ;

	/*	初期化処理	*/
	if (MMI_Open( &mmi ) == NOERR)
	{
		/*	初期化に成功すればメインループに入る.	*/
		if (APL_init() == NOERR)
		{
			MMI_ExecSystem() ;
			ICNTerm();
		}
	}

	/*	終了処理	*/
	MMI_Close() ;

}

int APL_init()
{
	extern MMIINIT	initDataGUI ;

	int	ret,mret,mptr ;

	mret = MG_PushPtr(MB_WAIT,&mptr);		//	MB_WAIT==目覚まし時計

	/*	EGB ワークアドレスの取得.	*/
	guiEgbPtr = MMI_GetEgbPtr() ;

	/*	ユーザアイコン設定		*/
	extern unsigned char *iconTbl[];
	extern int iconMaxId;
	MMI_SetIconTable(iconTbl, iconMaxId);

	/*	ハイパ型部品の初期化			*/
	if ((ret = MMI_initHyper()) < 0)
		return ret ;
	/*	ダイアログ型部品の初期化		*/
	if ((ret = MMI_initDialogL40()) < 0)
		return ret ;
	/*	ボタン型部品の初期化			*/
	if ((ret = MMI_initButtonL40()) < 0)
		return ret ;
	/*	アイコンボタン型部品の初期化	*/
	if ((ret = MMI_initIconL40()) < 0)
		return ret ;

	/*	背景データの初期化						*/

	/*	データの登録		*/
	if ((ret = MMI_Init(&initDataGUI)) < 0)
		return ret ;

	//	Tmenuにパレットを合わせる
	KH_initGuiColor();

	ICNInit(0);

	//自分とシェルのアプリIDを取得
	myID = MMI_GetApliId();
	shellID = MMI_CallMessage( myID, GM_QUERYID, QM_ALLKIND, 0 );

	//乱数まぜまぜ
	int b,x,y;
	MOS_rdpos(&b,&x,&y);
	srand(b+(x<2)+(y<3));

	//画面の大きさ取得
	getScreenSize();

	//始めの位置
	g_X = screen.lupx + (rand() % (screen.rdwx-screen.lupx)) ;
	g_Y = screen.lupy + (rand() % (screen.rdwy-screen.lupy)) ;
	g_Angle = rand() & 7;
	#ifdef DEBUG
	printf("start(%d,%d)|Angle=%d\n",g_X,g_Y,g_Angle);
	#endif
	gfr.lupx = g_X;
	gfr.lupy = g_Y;
	gfr.rdwx = g_X+23;
	gfr.rdwy = g_Y+23;
	MMI_SendMessage(dialogID,MM_MOVE,1,&gfr);

	/*	背景を表示する							*/
	MMI_SendMessage(MMI_GetBaseObj(), MM_SHOW, 0) ;

	MMI_SendMessage(MMI_GetBaseObj(), MM_SETEXEC, 1, userFunc);
	MMI_CallMessage(myID, GM_TITLE, (int)"ごき♪                          By 機拡", 0);

	extern void userIdleTask(void);
	//	アイドルタスク登録
	MMI_SetIdleTaskFunc( userIdleTask );

	//始めの移動方向セット
	setDirectory();

	//バックグラウンド
	toBackGround();

	if(mret==0) MG_PopPtr( mptr );

	return NOERR ;
}

void	userIdleTask(void)
{
	if(g_Count<2)
	{
		if(g_Count==1)	//停止したばっかり
		{
			(( POINT * )&( gev.info ))->x = g_X+12;
			(( POINT * )&( gev.info ))->y = g_Y+12;
			g_Count=0;
			#ifdef DEBUG
			printf("center(%d,%d)\n",g_X+12,g_Y+12);
			#endif
		}
		int apliID;
		apliID = MMI_CallMessage( myID , GM_ONPARTS, ( int )&gev, 0 );
		#ifdef DEBUG
		printf("apli=%d|my=%d|shell=%d\n",apliID,myID,shellID);
		#endif
		if((apliID == shellID) || (apliID == myID))
		{	//次の移動方向を決める
			setDirectory();
		}
	} else
	{	//ごきの移動
		#ifdef DEBUG
		printf("move(%d,%d)->",g_X,g_Y);
		#endif
		char flag=0;
		g_X += xx[g_Angle] ;
		g_Y += yy[g_Angle] ;
		if(g_X<screen.lupx) {g_X=screen.lupx;flag=1;}
		else if(g_X>screen.rdwx) {g_X=screen.rdwx;flag=1;}
		if(g_Y<screen.lupy) {g_Y=screen.lupy;flag=1;}
		else if(g_Y>screen.rdwy) {g_Y=screen.rdwy;flag=1;}
		if(flag==1)
		{
			g_Angle += 2;
			if(g_Angle>7) g_Angle -= 8;
		}
		#ifdef DEBUG
		printf("(%d,%d)\n",g_X,g_Y);
		#endif
		gfr.lupx = g_X;
		gfr.lupy = g_Y;
		gfr.rdwx = g_X+23;
		gfr.rdwy = g_Y+23;
		MMI_SendMessage(iconID,MM_SETSHAPE,1,512+(g_Angle<<1)+(g_Count&1) );
		MMI_SendMessage(dialogID,MM_ERASE,0);
		MMI_SendMessage(dialogID,MM_MOVE,1,&gfr);
		MMI_SendMessage(dialogID,MM_SHOW,0);
		#ifdef DEBUG
		printf("(%d,%d)-(%d,%d)|Angle=%d|Count=%d|Icon=%d\n",
				gfr.lupx,gfr.lupy,gfr.rdwx,gfr.rdwy,
				g_Angle,g_Count,512+(g_Angle<<1)+(g_Count&1) );
		#endif
		--g_Count;
	}

	return ;
}

void	setDirectory(void)
{
	g_Angle += ((rand() & 3) - 1);
	if(g_Angle>7) g_Angle = (g_Angle % 8);
	g_Count = 2+(rand() & 15);
	#ifdef DEBUG
	printf("NewAngle=%d|NewCount=%d\n",
			g_Angle,g_Count);
	#endif

	return ;
}

void	toBackGround(void)
{
	MMI_CallMessage( myID, GM_SLEEP, 0 , 0);

	if(myID==MMI_CallMessage( myID, GM_QUERYID, QM_ALLKIND, 1))
		MMI_CallMessage( myID, GM_TASKLIST, 0, 0 );

	return ;
}

void	getScreenSize(void)
{
	WINCTRL *pctrl ;
	//	WINCTRL構造体から画面最大サイズ（現在の解像度）を取得する
	MMI_GetControl(&pctrl) ;
	screen.lupx = pctrl->bound.lupx;
	screen.lupy = pctrl->bound.lupy;
	screen.rdwx = pctrl->bound.rdwx-24;
	screen.rdwy = pctrl->bound.rdwy-24;

	int flag=0;
	if(g_X<screen.lupx) {g_X=screen.lupx;flag=1;}
	else if(g_X>screen.rdwx) {g_X=screen.rdwx;flag=1;}
	if(g_Y<screen.lupy) {g_Y=screen.lupy;flag=1;}
	else if(g_Y>screen.rdwy) {g_Y=screen.rdwy;flag=1;}
	if(flag==1)
	{
		g_Angle += 2;
		if(g_Angle>7) g_Angle -= 8;
	}

	#ifdef DEBUG
	printf("scr(%d,%d)-(%d,%d)\n",
			screen.lupx,screen.lupy,screen.rdwx,screen.rdwy);
	#endif

	return ;
}
