//--------------------------------------------------------------------------------------
//
// X-BASIC'
//	外部関数：iOS用 Accesory
//
//--------------------------------------------------------------------------------------
// 外部関数の構造を持っている

#import "libs.h"
#include "fdef.h"
#include "support.h"
#include "XB.h"
#import	"RunViewController.h"

//---------------------------------------------------------------------------------------------
// 共通ワーク

// これは内部で設定
static	RunViewController *runView;

//---------------------------------------------------------------------------------------------

// この外部関数のバージョンを返す
static RET_FUNC _F_version(SWord numFAC,FAC fac[])
{
	printFunc();
	fac[0].dl.cp[LL]=VERSION_XBIOSFUNCA;
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_osVersion(SWord numFAC,FAC fac[])
{
	printFunc();
//	nslog(@"osVersion=%f",(double)getSystemVersion());
	fac[0].dl.d=getSystemVersion();
//	nslog(@"osVersion=%f",fac[0].dl.d);
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_deviceType(SWord numFAC,FAC fac[])
{
	printFunc();
	fac[0].dl.l[LL]=getDeviceType();
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_devicePlatform(SWord numFAC,FAC fac[])
{
	printFunc();
	fac[0].dl.bp[LL]=unsStringTocString(getDeviceModelName());
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_isLocalizeJapan(SWord numFAC,FAC fac[])
{
	printFunc();
	
	fac[0].dl.l[LL]=c2basicYESNO(isLocalizeJapan());
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

static RET_FUNC _F_getLanguage(SWord numFAC,FAC fac[])
{
	printFunc();
	
	fac[0].dl.bp[LL]=unsStringTocString(getLanguage());
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// v3.00
// int forcedSJIS(mode;int)
// 実行中の強制SHIFT-JISモードを設定する
// mode=0 (NO) :OFFにする
//     =-1(YES):ONにする
//	   =1 : 設定の強制SHIFT-JISモードを読み出すのみ
//	   =2 : 現在の強制SHIFT-JISモードを読み出すのみ
static RET_FUNC _F_forcedSJIS(SWord numFAC,FAC fac[])
{
	printFunc();
	int bmode=fsjisInRun; // 変更前の動作モードを返す
	int mode=2; // 省略時は2
	if (fac[0].facType!=VOID_PARAM) { // 引数が省略されていない時
		mode=(int)fac[0].dl.l[LL];
		nslog(@"モード指定あり:%d",mode);
	}
	nslog(@"forcedSJIS mode=%d",mode);
	switch (mode) {
		case BASIC_NO:
			fsjisInRun=NO;
			nslog(@"OFF");
			break;
		case BASIC_YES:
			fsjisInRun=YES;
			nslog(@"ON");
			break;
		case 1:
			bmode=operationStatus.fsjis;
			nslog(@"read setup");
			break;
		case 2:
			bmode=fsjisInRun;
			nslog(@"read now");
			break;
	}
	
	fac[0].dl.l[LL]=c2basicYESNO(bmode);
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// v3.00
// 現在の最大文字列長を返す
// 設定はできない
static RET_FUNC _F_maxStringLength(SWord numFAC,FAC fac[])
{
	fac[0].dl.l[LL]=operationStatus.sz_str-1; // EOSは引いておく
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}


// v3.10
// 現在のfopen()のエラー値を設定/返す
// int errorCodeFopen([mode;int])
static RET_FUNC _F_errorCodeFopen(SWord numFAC,FAC fac[])
{
	printFunc();
	int code=errorCodeFopenInRun; // 変更前のエラーコードを返す
	if (fac[0].facType!=VOID_PARAM) { // 引数が省略されていない時
		BOOL mode=basic2cYESNO(fac[0].dl.l[LL]);
		nslog(@"モード指定あり:%d",mode);
		switch ((int)mode) {
			case YES: // 新
				errorCodeFopenInRun=-1;
				break;
			case NO:  // 旧
				errorCodeFopenInRun=0;
				break;
		}
	} // 省略された時は現在のエラーコードを返す
	fac[0].dl.l[LL]=code; // 変更前のコードを返す
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

//---------------------------------------------------------------------------------------------
// デバッグ用関数：v3.20
//---------------------------------------------------------------------------------------------

// デバッグ画面出力関数
static void debugPrintFunc(NSString *text)
{
//	nslog(@"debugPrintFunc:runVC=%@",runView);
	[runView addDebugText:text];
#ifdef DEBUG
	fputs(nsStringTocString(text),stdout);
#endif
}

// デバッグモードを設定する
// void debugMode(mode;int,dumpMode;int)
static RET_FUNC _F_debugMode(SWord numFAC,FAC fac[])
{
	printFunc();
	operationStatus.debugMode		=fac[0].dl.l[LL];
	operationStatus.debugDumpMode	=fac[1].dl.l[LL];
	nslog(@"operationStatus.debugMode=$%x"		,operationStatus.debugMode);
	nslog(@"operationStatus.debugDumpMode=$%x"	,operationStatus.debugDumpMode);
	
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// 変数をダンプする
// void debugDump([dumpMode;int][,mes;str])
static RET_FUNC _F_debugDump(SWord numFAC,FAC fac[])
{
	printFunc();
	int dumpMode=DUMP_VAR_ALL|DUMP_DIM_ALL; //|DUMP_DIM_WITH_ELEMENTS;
	if (fac[0].facType!=VOID_PARAM) { // 引数が省略されていない時
		dumpMode=fac[0].dl.l[LL];
		nslog(@"モード指定あり:$%x",dumpMode);
	}
	char *mes="";
	if (fac[1].facType!=VOID_PARAM) { // 引数が省略されていない時
		mes=(char *)bstrWithUTF8(fac[1].dl.bp[LL]);
		nslog(@"メッセージ:%@",@(mes));
	}
	
	varDump(dumpMode,mes,debugPrintFunc);
	[runView updateDebugScreen]; // デバッグ画面を開いたまま再実行した時のため更新処理を入れる
	
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// debugPrint([mes;str])
// デバッグ画面に表示する
static RET_FUNC _F_debugPrint(SWord numFAC,FAC fac[])
{
	printFunc();
	//
	NSString *mes=@"\n"; // mes指定なしの時は改行
	if (fac[0].facType!=VOID_PARAM) { // 引数が省略されていない時
		mes=[NSString stringWithFormat:@"%@\n",@(bstrWithUTF8(fac[0].dl.bp[LL]))];
	}
	nslog(@"mes=%@",mes);
	debugPrintFunc(mes); // UTF8のみ
	[runView updateDebugScreen]; // デバッグ画面を開いたまま再実行した時のため更新処理を入れる
	//
	fac[0].dl.l[LL]=0; // 念のため
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

// programName$()
// プログラム名を返す
static RET_FUNC _F_programName(SWord numFAC,FAC fac[])
{
	printFunc();
	//
	fac[0].dl.cp[LL]=operationStatus.programName;
	nslog(@"プログラム名=%@",@(operationStatus.programName));
	fac[0].facType=FACTYPE_RETURN;
	return (RET_FUNC_OK); // OK
}

//---------------------------------------------------------------------------------------------
// インフォメーションテーブル (5.2.1章)
//---------------------------------------------------------------------------------------------

// 関数名テーブル(トークンテーブル)
static const char *iOSATokens[]={
	"osVersion",
	"deviceType",
	"devicePlatform",
	"isLocalizeJapan",
	"getLanguage$",
	"programName$",		// v3.20
	//
	"forcedSJIS",		// v3.00
	"maxStringLength",	// v3.00
	"errorCodeFopen",	// v3.10
	//
	"debugMode",		// v3.20
	"debugDump",		// v3.20
	"debugPrint",		// v3.20
	// バージョン
	"versionXBiOSAccesory$",
	// end of table
	NULL,
};

// 実行アドレステーブル
static FUNC_EXEC iOSAFuncExec[]={
	// Cの標準関数名と重複させないよう_F_を付ける
	{_F_osVersion},
	{_F_deviceType	},
	{_F_devicePlatform},
	{_F_isLocalizeJapan},
	{_F_getLanguage},
	{_F_programName},		// v3.20
	//
	{_F_forcedSJIS},		// v3.00
	{_F_maxStringLength},	// v3.00
	{_F_errorCodeFopen}, 	// v3.10
	//
	{_F_debugMode},			// v3.20
	{_F_debugDump},			// v3.20
	{_F_debugPrint},		// v3.20
	// バージョン
	{_F_version},
	// end of table
	{NULL},
};

//------------------------------
// パラメーターテーブル
// (1)種類別定義
// 1関数の引数は最大MAX_PARAM個

static const uwPARAMTYPE p_osVersion[]={
	FLOAT_RET,
};

static const uwPARAMTYPE p_deviceType[]={
	INT_RET,
};
#define	p_isLocalizeJapan	p_deviceType
#define	p_maxStringLength	p_deviceType

static const uwPARAMTYPE p_version[]={
	STR_RET,
};
#define p_getLanguage		p_version
#define p_devicePlatform	p_version
#define p_programName		p_version

static const uwPARAMTYPE p_forcedSJIS[]={
	INT_OMT,
	INT_RET,
};
#define p_errorCodeFopen	p_forcedSJIS

static const uwPARAMTYPE p_debugMode[]={
	INT_VAL,
	INT_VAL,
	VOID_RET
};

static const uwPARAMTYPE p_debugDump[]={
	INT_OMT,
	STR_OMT,
	VOID_RET
};

static const uwPARAMTYPE p_debugPrint[]={
	STR_OMT,
	VOID_RET,
};

//------------------------------
// パラメーターテーブル
// (2)関数別定義

static
const
uwPARAMTYPE *iOSAParams[]={
	p_osVersion	,
	p_deviceType	,
	p_devicePlatform,
	p_isLocalizeJapan,
	p_getLanguage,
	p_programName,
	//
	p_forcedSJIS,
	p_maxStringLength,
	p_errorCodeFopen,
	//
	p_debugMode,
	p_debugDump,
	p_debugPrint,
	// バージョン
	p_version	,
	// end of table
	NULL,
};

//-------------

// この中の関数の初期化処理
static void _Finit(void)
{
	printFunc();
	// 実行開始時にデバッグ画面を初期設定する
	// _Frunでなくここでクリアするのは、enumチェック中は_Frunが走る前なので
	runView=xb_getRunView();
	nslog(@"Acc:runView=%@",runView);
	operationStatus.debugPrintFunc=debugPrintFunc;
	nslog(@"programName=%@",@(operationStatus.programName));
	runView.debugText=@(operationStatus.programName);
}

static void _Frun(void)
{
	printFunc();
}

// この中の関数の終了処理
static void _Fend(void)
{
	printFunc();
}

// インフォメーションテーブル
const
INFORMATION_TABLE	InfoIosAFuncs={
	#ifdef FUNC_DEBUG
	"iOS Accesory functions",
	#endif
	_Finit,		// Finit
	_Frun,		// Frun
	_Fend,		// Fend
	returnOnly,	// Fexit
	returnOnly,	// Fbreak
	NULL,		// FctrlD;未使用
	NULL,		// 予約1
	NULL,		// 予約2
	//
	iOSATokens,
	iOSAParams,
	iOSAFuncExec
};

//---------------------------------------------------------------------------------------------
