#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 <mos.h>
//#define DEBUG
#define ERROR	(-1)
#define LINESIZE (256)
#define MAXCLASS (10)

extern int topMenuID[] ;
extern int sourceMenuID ;
extern int sourceMenuItemID ;

int readMenuFunc(void);
int init(void);
void end(void);
int attachMenu(void);
int addMenuItem( int );
int nextMenu(void);
int nextLine(void);
int nextWord(void);

//	メモリロット
int		memLotID;		//	アプリ終了まで使用
int		tempMemLotID;	//	一時的に使用
//	単語抽出処理用
char	*line;				//一行
char	*buf;				//単語
int		count;				//読み込んだ一行の何文字目か
FILE	*fp;
//	メニュー情報
int		*menuID;			//メニューID
int		*menuParentNum;		//親メニューアイテムの番号
int		*menuXsize;			//メニューのXサイズ
int		*menuYsize;			//メニューのYサイズ
//	メニュー構成用
int		menuNum;			//メニューの数
//	メニューアイテム情報
int		*menuItemID;		//メニューアイテムID
int		*menuItemParentID;	//親メニューアイテムID
char	*menuItemMsg;		//メニューアイテムメッセージ(ロット確保)
int		*menuItemChar;		//メニューアイテムメッセージサイズ(ドット)
//	メニューアイテム構成処理用
int		menuItemNum;		//メニューアイテムの数
int		parentID[MAXCLASS];	//親MenuのID
int		class;				//階層(一番上=0)
//	アプリ情報
int		*apliID;			//アプリに対応するメニューアイテムID(ロット確保)
int		*apliMode;			//アプリMODE(ロット確保)
char	*apliPath;			//アプリパス(ロット確保)
int		*apliSaveFlag;		//アプリ退避フラグ(sub.cで使用)(ロット確保)
//	アプリ構成処理用
int		apliNum;			//アプリメニューの数

int		masterMenuID;

int readMenuFunc(void)
{

	//読み込み開始
	if(init()!=NOERR) return ERROR;

	//一番上のメニュー
	masterMenuID = topMenuID[1];
	parentID[0] = masterMenuID;
	#ifdef DEBUG
	printf("master'topMenuID[1]'=%d\n",masterMenuID);
	#endif
	class = 0;
	menuNum = 0;
	menuItemNum = 0;
	apliNum = 0;
	//メニュー構成読み込み･解析
	while(nextWord()==NOERR)
	{
		if(buf!=NULL)
		{
			if(buf[0]==':') nextMenu();
			else
			{
				addMenuItem(TRUE);
			}
		}
	}
	//メニュー接続
	attachMenu();

	//読み込み終了
	end();

	return NOERR ;
}

int attachMenu(void)
{
	int		i,j;
	int		mx,my;
	int		Xsize,Ysize;
	HYPER	hyp;
	FRAME	fr;

	#ifdef DEBUG
	printf("attach:\nmenu=%d\nmenuItem=%d\napli=%d\n",
									menuNum,menuItemNum,apliNum);
	#endif

	//マスターメニューへの接続と位置設定
	MMI_SendMessage(masterMenuID,MM_GETHYPER,1,&hyp);
	mx=hyp.fr.lupx;
	my=hyp.fr.lupy;
	//子を探す(最大Xサイズ設定)
	Xsize=0;
	for(j=0;j<menuItemNum;j++)
	{
		if(masterMenuID==menuItemParentID[j])
		{
			if(Xsize<menuItemChar[j]) Xsize = menuItemChar[j];
		}
	}
	//子を探す(ATTACH,MOVE処理)
	Ysize=0;
	for(j=0;j<menuItemNum;j++)
	{
		if(masterMenuID==menuItemParentID[j])
		{	//ATTACHする
			MMI_SendMessage(menuItemID[j],MM_ATTACH,1,masterMenuID);
			//移動する
			fr.lupx = mx+1;
			fr.lupy = my+1+Ysize*16;
			fr.rdwx = fr.lupx+Xsize;
			fr.rdwy = fr.lupy+15;
			MMI_SendMessage(menuItemID[j], MM_MOVE, 1, &fr ); 
			++Ysize;
		}
	}
	//マスターメニュー位置設定
	MMI_SendMessage(masterMenuID,MM_GETHYPER,1,&hyp);
	hyp.fr.rdwx = hyp.fr.lupx+Xsize+4;
	hyp.fr.rdwy = hyp.fr.lupy+Ysize*16+3;
	MMI_SendMessage(masterMenuID,MM_SETHYPER,1,&hyp);

	//メニューアイテム接続と位置設定
	for(i=0;i<menuNum;i++)
	{
		MMI_SendMessage(menuID[i],MM_GETHYPER,1,&hyp);
		mx=hyp.fr.lupx;
		my=hyp.fr.lupy;
		//子を探す(最大Xサイズ設定)
		Xsize=0;
		for(j=0;j<menuItemNum;j++)
		{
			if(menuID[i]==menuItemParentID[j])
			{
				if(Xsize<menuItemChar[j]) Xsize = menuItemChar[j];
			}
		}
		menuXsize[i] = Xsize;
		//子を探す(ATTACH,MOVE処理)
		Ysize=0;
		for(j=0;j<menuItemNum;j++)
		{
			if(menuID[i]==menuItemParentID[j])
			{	//ATTACHする
				MMI_SendMessage(menuItemID[j],MM_ATTACH,1,menuID[i]);
				//移動する
				fr.lupx = mx+1;
				fr.lupy = my+1+Ysize*16;
				fr.rdwx = fr.lupx+Xsize;
				fr.rdwy = fr.lupy+15;
				MMI_SendMessage(menuItemID[j], MM_MOVE, 1, &fr ); 
				++Ysize;
			}
		}
		menuYsize[i] = Ysize*16;
	}
	//メニュー位置設定
	for(i=0;i<menuNum;i++)
	{
		MMI_SendMessage(menuItemParentID[menuParentNum[i]],MM_GETHYPER,1,&hyp);
		fr.lupx = hyp.fr.rdwx;
		MMI_SendMessage(menuItemID[menuParentNum[i]],MM_GETHYPER,1,&hyp);
		fr.lupy = hyp.fr.lupy;
		fr.rdwx = fr.lupx+menuXsize[i]+4;
		fr.rdwy = fr.lupy+menuYsize[i]+3;
		MMI_SendMessage(menuID[i], MM_MOVE, 1, &fr ); 
	}

	return NOERR;
}

int addMenuItem(int flag)
{
	int i,j;

	//新たなメニューアイテムを追加する
	//新IDを創造
	menuItemID[menuItemNum] = MMI_SendMessage(sourceMenuItemID,MM_NEW,0);
	//親IDを登録(attachは後で)
	menuItemParentID[menuItemNum] = parentID[class];
	//メッセージを情報領域に複写して登録
	j=menuItemNum*20;
	if(flag==TRUE)
	{
		for(i=0;buf[i]!='\0';i++)
			menuItemMsg[j+i] = buf[i];
		menuItemMsg[j+i] = '\0';
		menuItemChar[menuItemNum] = i*6+12;
	} else
	{
		for(i=0;buf[i+1]!='\0';i++)
			menuItemMsg[j+i] = buf[i+1];
		menuItemMsg[j+i] = '\0';
		menuItemChar[menuItemNum] = i*6+18;
	}
	MMI_SendMessage(menuItemID[menuItemNum],MM_SETMSG,1,&(menuItemMsg[j]));

	#ifdef DEBUG
	printf("%c%d|%d|%s%c",(flag==TRUE ? 'I' : 'G'),
		class,parentID[class],&(menuItemMsg[j]),(flag==TRUE ? '|' : '\n'));
	#endif

	if(flag==TRUE)
	{														//アプリの追加
		//アプリに対応するメニューアイテムのIDを保存
		apliID[apliNum] = menuItemID[menuItemNum];
		//アプリのモードを保存
		nextWord();
		apliMode[apliNum] = atoi(buf);
		//アプリのパスを保存
		nextWord();
		j=apliNum*128;
		for(i=0;buf[i]!='\0';i++)
			apliPath[j+i] = buf[i];
		apliPath[j+i] = '\0' ;

		#ifdef DEBUG
		printf("%d|%s\n",apliMode[apliNum],&(apliPath[j]));
		#endif

		++apliNum;
	}

	++menuItemNum;

	return NOERR;
}

int nextMenu(void)
{
	int flag;

	//新たなメニューアイテムを追加する
	addMenuItem(FALSE);

	++class;
	//新たなメニューを作る
	//新IDを創造
	menuID[menuNum] = MMI_SendMessage(sourceMenuID,MM_NEW,0);
	parentID[class] = menuID[menuNum] ;
	//親メニューアイテムにattachする
	menuParentNum[menuNum] = menuItemNum-1;
	MMI_SendMessage(menuID[menuNum],MM_ATTACH,1,menuItemID[menuItemNum-1]);

	++menuNum;

	nextWord();
	if(buf[0]!='{') return ERROR;
	flag = FALSE;
	do {
		nextWord();
		if(buf[0]==':')
			nextMenu();
		else
			if(buf[0]=='}') flag=TRUE;
			else
				addMenuItem(TRUE);
	} while(flag==FALSE);

	--class;

	return NOERR;
}

int nextWord(void)
{
	char c;
	int i,flag,flag2;

	flag = FALSE;
	do {
		do {
			c=line[count++] ;
		} while(c==' ' || c=='\t' || c==',') ;

		if(c=='#' || c=='\n' || c=='\0')
		{
			if(nextLine()==ERROR) return ERROR;
		} else flag = TRUE;
	} while (flag==FALSE);

	if(c=='"')
	{
		flag2=TRUE;
		c=line[count++] ;
	} else
		flag2=FALSE;

	i=0;
	flag = FALSE;
	do {
		buf[i++] = c ;
		c = line[count++] ;

		if(c==' ' || c=='\t' || c==',' || c=='#' || c=='\n' || c=='\0')
		{
			if(c=='\t' && flag2==TRUE)
			{
				buf[i  ] = ' ';		buf[i+1] = ' ';
				buf[i+2] = ' ';
				i += 3;
				c = ' ';
			} else if(c!=' ' || flag2==FALSE)
			{
				flag=TRUE;
				buf[i]='\0';
				if(c=='#' || c=='\n' || c=='\0') line[count] = '\0';
			}
		}

	} while(flag == FALSE);
	if(flag2==TRUE) buf[i-1] = '\0';

	return NOERR;
}

int nextLine(void)
{
	if(fgets(line,LINESIZE,fp)==NULL)
		return ERROR;
	count = 0;

	return NOERR;
}

int init(void)
{
	int i;

	//メモリロット確保
	memLotID = TL_getLot();
	tempMemLotID = TL_getLot();

	//単語抽出処理用バッファ獲得
	if((line = TL_mallocMemory(tempMemLotID,LINESIZE))==NULL) return ERROR;
	if((buf  = TL_mallocMemory(memLotID,LINESIZE))==NULL) return ERROR;

	//ファイルオープン
	MMI_CallMessage(MMI_GetApliId(),GM_QUERYID,QM_DIRECTRY,( int )buf );
	for(i=0;buf[i]!='\0';i++) ;
	buf[i   ] = 'T';	buf[i+ 1] = 'A';	buf[i+ 2] = 'S';
	buf[i+ 3] = 'K';	buf[i+ 4] = 'M';	buf[i+ 5] = 'A';
	buf[i+ 6] = 'N';	buf[i+ 7] = 'A';	buf[i+ 8] = '.';
	buf[i+ 9] = 'M';	buf[i+10] = 'N';	buf[i+11] = 'U';
	buf[i+12] = '\0';
	if((fp = EIN_fopen( buf, "rt" ))==NULL)
		return ERROR;

	if(nextLine()==ERROR) return ERROR;

	//メニュー等の数を数える
	menuItemNum = 0;
	menuNum = 0;
	apliNum = 0;
	while(nextWord()==NOERR)
	{
		if(buf!=NULL)
		{
			if(buf[0]!='{' && buf[0]!='}')
			{
				for(i=0;buf[i]=='\0';i++) if(buf[i]=='}') return ERROR;
				++menuItemNum;
				if(buf[0]==':') ++menuNum;
				else
				{
					++apliNum;
					nextWord();	//モード空読み
					nextWord();	//パス空読み
				}
			}
		}
	}

	#ifdef DEBUG
	printf("menu=%d\nmenuItem=%d\napli=%d\n",menuNum,menuItemNum,apliNum);
	#endif

	if((menuID=(int *)TL_mallocMemory(tempMemLotID,menuNum*4))==NULL)
		return ERROR;
	if((menuParentNum=(int *)TL_mallocMemory(tempMemLotID,menuNum*4))==NULL)
		return ERROR;
	if((menuXsize=(int *)TL_mallocMemory(tempMemLotID,menuNum*4))==NULL)
		return ERROR;
	if((menuYsize=(int *)TL_mallocMemory(tempMemLotID,menuNum*4))==NULL)
		return ERROR;
	if((menuItemID=(int *)TL_mallocMemory(tempMemLotID,menuItemNum*4))==NULL)
		return ERROR;
	if((menuItemParentID=
					(int *)TL_mallocMemory(tempMemLotID,menuItemNum*4))==NULL)
		return ERROR;
	if((menuItemMsg= TL_mallocMemory(memLotID,menuItemNum*20))==NULL)
		return ERROR;
	if((menuItemChar=
					(int *)TL_mallocMemory(tempMemLotID,menuItemNum*4))==NULL)
		return ERROR;
	if((apliID=(int *)TL_mallocMemory(memLotID,apliNum*4))==NULL)
		return ERROR;
	if((apliMode=(int *)TL_mallocMemory(memLotID,apliNum*4))==NULL)
		return ERROR;
	if((apliPath=TL_mallocMemory(memLotID,apliNum*128))==NULL)
		return ERROR;
	if((apliSaveFlag=(int *)TL_mallocMemory(memLotID,apliNum*4))==NULL)
		return ERROR;

	//巻き戻す
	fseek(fp,0,SEEK_SET);
	//最初の行をセット
	nextLine();

	return NOERR;
}

void end(void)
{
	//作業用ロット開放
	TL_freeLot( tempMemLotID ); 

	//ファイルクローズ
	fclose(fp);

	return ;
}

