#pragma mark ----------

#define ALLOW_ACCESS_TO_INTERNALS_OF_MENUS

#include <PalmOS.h>
#include "PalmChars.h"
#include "T-Suite.h"
#include "T-Suite.rsrc.h"

#pragma mark ----------

TSuitePreferenceType tempPrefs;

#define ftr_appHackTrapAddress	0x10	//Ftr

#pragma mark ----------

typedef Err (*EvtGetEventTrapType)
	(EventType *event, Int32 timeout);

#pragma mark ----------

static void DeactivateTrapHack(void)
{
	UInt32 trapadd;

	if (FtrGet (appFileCreator, ftr_appHackTrapAddress, &trapadd) == 0)
	{
		SysSetTrapAddress (sysTrapEvtGetEvent, (UInt32*)trapadd);
		FtrUnregister (appFileCreator, ftr_appHackTrapAddress);
	}
}

static Err EvtGetEventTrapHack(EventType *event, Int32 timeout)
{
	UInt32 oldtrapadd;
	EvtGetEventTrapType oldTrap;

	FtrGet (appFileCreator, ftr_appHackTrapAddress, &oldtrapadd);

	oldTrap = (EvtGetEventTrapType)oldtrapadd;

	Err error = oldTrap(event, timeout);

	SysNotifyParamType notify;
	notify.notifyType = sysNotifyEventDequeuedEvent;
	notify.broadcaster = 'psys';
	notify.notifyDetailsP = event;
	notify.userDataP = 0;
	notify.handled = false;
	notify.reserved2 = 0;

	SysNotifyBroadcast(&notify);

	return error;
}

static void ActivateTrapHack(void)
{
	UInt32 trapadd;
	if (FtrGet (appFileCreator, ftr_appHackTrapAddress, &trapadd) != 0)
	{
		trapadd = (UInt32)SysGetTrapAddress (sysTrapEvtGetEvent);
		FtrSet (appFileCreator, ftr_appHackTrapAddress, (UInt32)SysGetTrapAddress (sysTrapEvtGetEvent));
		SysSetTrapAddress (sysTrapEvtGetEvent, &EvtGetEventTrapHack);
	}
}

#pragma mark ----------

static void SetTSuitePreference(TSuitePreferenceType *prefs)
{
	PrefSetAppPreferences (appFileCreator, appPrefID, appPrefVersionNum, 
		prefs, sizeof (TSuitePreferenceType), false);
}

static void GetTSuitePreference (TSuitePreferenceType *prefs)
{
	UInt16 prefsSize;
	prefsSize = sizeof (TSuitePreferenceType);
	if (PrefGetAppPreferences (appFileCreator, appPrefID, prefs, &prefsSize, false) == 
		noPreferenceFound)
		{
			UInt32 ftrValue;
			if (FtrGet (appFileCreator, ftr_appStatus, &ftrValue) == errNone)
			{
				TSuitePreferenceType *prefsP = (TSuitePreferenceType*)ftrValue;
				MemMove (prefs, prefsP, sizeof (TSuitePreferenceType));
			}
			else
			{
				prefs->appLocalID = NULL;				// TSut
				prefs->capsLock = NULL;					// FTgl
				prefs->numLock = NULL;					// FTgl
				prefs->tempShift = NULL;				// FTgl
				prefs->autoShifted = NULL;				// FTgl
	 			prefs->OnF = IsOff;						// TSut
	 			prefs->OffF = IsOn;						// TSut
	 			prefs->AutoEnbleAfterResetF = IsOff;	// TSut
				prefs->numButtons = NULL;				// WbMn
				prefs->FEPModeControlF = IsOn;			// FTgl
	 			prefs->AddNichiEiBtnF = IsOff;			// Ftgl
	 			prefs->AddHiraKataBtnF = IsOff;			// FTgl
	 			prefs->AddHenkanBtnF = IsOff;			// FTgl
				prefs->AddBtnBackLitONF = IsOff;		// FTgl
	 			prefs->UnUsed = NULL;					// UnUsed
 				prefs->BtnInsPosition = 0;				// WbMn
			}
		}

	SetTSuitePreference (prefs);
}

#pragma mark ----------

static void Disable(void)
{
	UInt16 cardNo;
	LocalID dbID;
	SysCurAppDatabase (&cardNo, &dbID);

	UInt32 value;
	if (!FtrGet (appFileCreator, ftr_appStatus, &value))
		Err error = MemHandleUnlock (DmGetResource ('code', 1));

	DmDatabaseProtect (cardNo, dbID, false);

	UInt16 attributes;
	DmDatabaseInfo (cardNo, dbID, NULL, &attributes, NULL, NULL, NULL, NULL,
		NULL, NULL, NULL, NULL, NULL);
	attributes = attributes & (~dmHdrAttrReadOnly);
	DmSetDatabaseInfo (cardNo, dbID, NULL, &attributes, NULL, NULL, NULL, NULL, NULL,
		NULL, NULL, NULL, NULL);

	DmOpenRef FEPBtnDbRef;
	DmSearchResource ('Tbmp', Btn_NichiEiBitmapFamily, NULL, &FEPBtnDbRef);
	if (FEPBtnDbRef)
		DmCloseDatabase (FEPBtnDbRef);

	SysNotifyUnregister(cardNo, dbID,
			sysNotifyMenuCmdBarOpenEvent, FTglPriority);
	SysNotifyUnregister(cardNo, dbID,
			appFileCreator, FTglPriority);
	SysNotifyUnregister(cardNo, dbID,
			sysNotifyEventDequeuedEvent, FTglPriority);

	FtrPtrFree (appFileCreator, ftr_appStatus);

	DeactivateTrapHack ();
}

static void Enable(void)
{

	TSuitePreferenceType prefs;
		GetTSuitePreference(&prefs);

	// clear temp values
	prefs.appLocalID = NULL;			// TSut
	prefs.capsLock = NULL;				// FTgl
	prefs.numLock = NULL;				// FTgl
	prefs.tempShift = NULL;				// FTgl
	prefs.autoShifted = NULL;			// FTgl
	prefs.numButtons = NULL;			// WbMn
	prefs.UnUsed = NULL;				// UnUsed

	UInt16 cardNo;
	LocalID dbID;
	SysCurAppDatabase (&cardNo, &dbID);

	UInt16 attributes;
	DmDatabaseInfo (cardNo, dbID, NULL, &attributes, NULL, NULL, NULL, NULL,
		NULL, NULL, NULL, NULL, NULL);
	attributes = attributes | dmHdrAttrReadOnly;
	DmSetDatabaseInfo (cardNo, dbID, NULL, &attributes, NULL, NULL, NULL, NULL, NULL,
		NULL, NULL, NULL, NULL);

	MemHandleLock (DmGetResource ('code', 1));

	DmDatabaseProtect (cardNo, dbID, true);

	prefs.appLocalID = dbID;

	TSuitePreferenceType *FEPTglPreferenceP; 
	FtrPtrNew (appFileCreator, ftr_appStatus,
			sizeof (TSuitePreferenceType), (void**)&FEPTglPreferenceP);
	DmWrite (FEPTglPreferenceP, 0, &prefs, sizeof (TSuitePreferenceType));

	if (prefs.FEPModeControlF == IsOn)
	{
		SysNotifyRegister (cardNo, dbID, sysNotifyMenuCmdBarOpenEvent,
//					 NULL, FTglPriority, (MemPtr)'FTgl');
					 &FTglCmdBarOpenHandle, FTglPriority, (MemPtr)'FTgl');
	}

	ActivateTrapHack ();
}

#pragma mark --- FTgl Dialogue Form -

static void GetFTglCtrlValue (FormPtr frmP, TSuitePreferenceType *prefs)
{
	if (FrmGetControlValue (frmP, FrmGetObjectIndex (frmP, FEPModeControlAddNichiEiBtnCheckbox  )) == true)
		prefs->AddNichiEiBtnF = IsOn; else prefs->AddNichiEiBtnF = IsOff;
	if (FrmGetControlValue (frmP, FrmGetObjectIndex (frmP, FEPModeControlAddHiraKataBtnCheckbox )) == true)
		prefs->AddHiraKataBtnF = IsOn; else prefs->AddHiraKataBtnF = IsOff;
	if (FrmGetControlValue (frmP, FrmGetObjectIndex (frmP, FEPModeControlAddHenkanBtnCheckbox   )) == true)
		prefs->AddHenkanBtnF = IsOn; else prefs->AddHenkanBtnF = IsOff;

	prefs->BtnInsPosition = (UInt8)(FrmGetControlGroupSelection (frmP, FEPModeControlGroupID)) - 8;

	if (FrmGetControlValue (frmP, FrmGetObjectIndex (frmP, FEPModeControlAddBtnBacklitONCheckbox)) == true)
		prefs->AddBtnBackLitONF = IsOn; else prefs->AddBtnBackLitONF = IsOff;
}

static void SetFTglCtrlValue (FormPtr frmP, TSuitePreferenceType *prefs)
{
	FrmSetControlValue (frmP, FrmGetObjectIndex (frmP, FEPModeControlAddNichiEiBtnCheckbox), prefs->AddNichiEiBtnF);
	FrmSetControlValue (frmP, FrmGetObjectIndex (frmP, FEPModeControlAddHiraKataBtnCheckbox), prefs->AddHiraKataBtnF);
	FrmSetControlValue (frmP, FrmGetObjectIndex (frmP, FEPModeControlAddHenkanBtnCheckbox), prefs->AddHenkanBtnF);
	CtlSetEnabled ((ControlType*)FrmGetObjectPtr (frmP, FrmGetObjectIndex (frmP, FEPModeControlDotPushButton)), false);		

	FrmSetControlGroupSelection (frmP, FEPModeControlGroupID, FEPModeControlRPushButton + prefs->BtnInsPosition);

	FrmSetControlValue (frmP, FrmGetObjectIndex (frmP, FEPModeControlAddBtnBacklitONCheckbox), prefs->AddBtnBackLitONF);
}

#pragma mark --- T-Suite Dialogue Form -

static void GetTSuiteCtrlValue (FormPtr frmP, TSuitePreferenceType *prefs)
{
	if (FrmGetControlValue (frmP, FrmGetObjectIndex (frmP, TSuiteONPushButton)) == true)
		prefs->OnF = IsOn; else prefs->OnF = IsOff;
	if (FrmGetControlValue (frmP, FrmGetObjectIndex (frmP, TSuiteOFFPushButton)) == true)
		prefs->OffF = IsOn; else prefs->OffF = IsOff;
	if (FrmGetControlValue (frmP, FrmGetObjectIndex (frmP, TSuiteAutoEnableafterResetCheckbox)) == true)
		prefs->AutoEnbleAfterResetF = IsOn; else prefs->AutoEnbleAfterResetF = IsOff;
}

static void SetTSuiteCtrlValue (FormPtr frmP, TSuitePreferenceType *prefs)
{
	FrmSetControlValue (frmP, FrmGetObjectIndex (frmP, TSuiteONPushButton), prefs->OnF);
	FrmSetControlValue (frmP, FrmGetObjectIndex (frmP, TSuiteOFFPushButton), prefs->OffF);
	FrmSetControlValue (frmP, FrmGetObjectIndex (frmP, TSuiteAutoEnableafterResetCheckbox), prefs->AutoEnbleAfterResetF);

	// Hide [FEP Mode Control Config Btn] when Btn Rsource was NotFound.
	LocalID FEPBtnDbID = DmFindDatabase (0, FEPBtnDbName);
	UInt16 objIndex = FrmGetObjectIndex (frmP, TSuiteFEPModeControlCnfGraphicButton);
	if (FEPBtnDbID)
		FrmShowObject (frmP, objIndex);
	else
	{
		FrmHideObject (frmP, objIndex);
		prefs->AddNichiEiBtnF = IsOff;			// Ftgl
		prefs->AddHiraKataBtnF = IsOff;			// FTgl
		prefs->AddHenkanBtnF = IsOff;			// FTgl
		SetTSuitePreference (prefs);
	}
}

#pragma mark ----------

static Boolean TSuiteDialogueFormHandle(EventPtr eventP)
{
	Boolean handled = false;
	FormPtr TSutFrmP;
	FormPtr FTglFrmP;

//	TSuitePreferenceType tempPrefs;
//	GetTSuitePreference (&tempPrefs);

	switch (eventP->eType) 
		{
		case frmOpenEvent:
			TSutFrmP = FrmGetActiveForm();
			SetTSuiteCtrlValue (TSutFrmP, &tempPrefs);			//Set TSut dialogue control value
			FrmDrawForm (TSutFrmP);
			handled = true;
			break;

		case ctlSelectEvent:
			switch (eventP->data.ctlSelect.controlID)
			{
			case TSuiteFEPModeControlInfGraphicButton:
				FrmAlert (FEPModeControlAlert);
				handled = true;
				break;

			case TSuiteFEPModeControlCnfGraphicButton:
				FTglFrmP = FrmInitForm (FEPModeControlForm);	//Initialize T-Suite dialogue form
				SetFTglCtrlValue (FTglFrmP, &tempPrefs);		//Set FTgl dialogue control value
				if (FrmDoDialog (FTglFrmP) == FEPModeControlDoneButton)
					GetFTglCtrlValue (FTglFrmP, &tempPrefs);	//Get FTgl dialogue control value
				FrmDeleteForm (FTglFrmP);
				handled = true;
				break;

			case TSuiteDoneButton:
				GetTSuiteCtrlValue (FrmGetActiveForm(), &tempPrefs);			//Get TSut dialogue control value
				SetTSuitePreference (&tempPrefs);

			case TSuiteCancelButton:
				GetTSuitePreference (&tempPrefs);

				if (tempPrefs.OnF)
				{	Disable ();
					Enable ();}
				else
					Disable ();
				
				EventType event;
				event.eType = appStopEvent;
				EvtAddEventToQueue (&event);

				FrmCloseAllForms ();

				handled = true;
				break;
			}
			break;

		case keyDownEvent:
			if (NavSelectPressed (eventP))
			{
				EventType event;
				event.eType = appStopEvent;
				EvtAddEventToQueue (&event);

				FrmCloseAllForms ();
			}
			handled = true;
			break;

		default:
			break;
		
		}
	
	return handled;
}

static Boolean AppHandleEvent(EventPtr eventP)
{
	UInt16 formId;
	FormPtr frmP;

	if (eventP->eType == frmLoadEvent)
		{
		// Load the form resource.
		formId = eventP->data.frmLoad.formID;
		frmP = FrmInitForm(formId);
		FrmSetActiveForm(frmP);
		GetTSuitePreference (&tempPrefs);

		// Set the event handler for the form.  The handler of the currently
		// active form is called by FrmHandleEvent each time is receives an
		// event.
		switch (formId)
			{
			case TSuiteForm:
				FrmSetEventHandler(frmP, TSuiteDialogueFormHandle);
				break;

			default:
				break;
			}
		return true;
		}
	return false;
}

static void AppEventLoop(void)
{
	UInt16 error;
	EventType event;

	do {
		EvtGetEvent(&event, evtWaitForever);

		if (! SysHandleEvent(&event))
			if (! MenuHandleEvent(0, &event, &error))
				if (! AppHandleEvent(&event))
					FrmDispatchEvent(&event);

	} while (event.eType != appStopEvent);
}

static UInt32 StarterPalmMain (UInt16 cmd, MemPtr cmdPBP, UInt16 launchFlags)
{
//	Err error;

	switch (cmd)
		{
		case sysAppLaunchCmdNormalLaunch:
			FrmGotoForm(TSuiteForm);
			AppEventLoop();
			FrmCloseAllForms ();
			break;

		case sysAppLaunchCmdNotify:
			SysNotifyParamType* NtfyPrm = (SysNotifyParamType*)cmdPBP;
			switch (NtfyPrm->notifyType)
				{
				case sysNotifyEventDequeuedEvent:
					switch ((UInt32)(NtfyPrm->userDataP))
					{
					case 'FTgl':
						FTglCmdBarKeyDownHandle (NtfyPrm);
						break;
					}
					break;

				case sysNotifyMenuCmdBarOpenEvent:
					switch ((UInt32)(NtfyPrm->userDataP))
					{
					case  'FTgl':
						FTglCmdBarOpenHandle (NtfyPrm);
						break;
					}
					break;

				case appFileCreator:
					switch ((UInt32)(NtfyPrm->userDataP))
					{
					case 'FTgl':
						FTglCmdBarOpenedHandle (NtfyPrm);
						break;
					}
					break;
				}
			break;

		case sysAppLaunchCmdSystemReset:
			TSuitePreferenceType prefs;
			GetTSuitePreference (&prefs);
			if (prefs.OnF == IsOn)
			{
				if (prefs.AutoEnbleAfterResetF == IsOn)
					Enable();						//activate
				else
				{
					Disable();
					prefs.OnF  = IsOff;
					prefs.OffF = IsOn;
				}
				SetTSuitePreference (&prefs);
			}
			break;

		default:
			break;
		}

	return errNone;
}

UInt32 PilotMain ( UInt16 cmd, MemPtr cmdPBP, UInt16 launchFlags)
{
	return StarterPalmMain (cmd, cmdPBP, launchFlags);
}
