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

#define ALLOW_ACCESS_TO_INTERNALS_OF_MENUS

#include <PalmOS.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->OnF = IsOff;						// TSut
	 			prefs->OffF = IsOn;						// TSut
	 			prefs->AutoEnbleAfterResetF = IsOff;	// TSut
				prefs->UpDownPushDetected = IsOff;		// WbMn
				prefs->MenuHwrKeyControlF = IsOff;		// WbMn *Tungsten/Zire=IsOn Other=IsOff
				prefs->ToolbarHwrKeyControlF = IsOff;	// WbMn
				prefs->OpenHwrKeyControlF = IsOff;		// WbMn
				prefs->prevCmdBtnIndex = NULL;			// WbMn
				prefs->numButtons = NULL;				// WbMn
				prefs->keyControlHandled = NULL;		// WbMn:temp
	 			prefs->UnUsed = NULL;					// UnUsed
			}
		}

	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);

	SysNotifyUnregister(cardNo, dbID,
			sysNotifyEventDequeuedEvent, WbMnPriority);

	SysNotifyUnregister(cardNo, dbID,
			sysNotifyEventDequeuedEvent, WbMmPriority);

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

	FtrPtrFree (appFileCreator, ftr_appStatus);

	DeactivateTrapHack ();
}

static void Enable(void)
{

	TSuitePreferenceType prefs;
		GetTSuitePreference(&prefs);

	// clear temp values
	prefs.appLocalID = NULL;			// TSut
	prefs.fldP = NULL;					// BlkS
	prefs.chr = NULL;					// BlkS
	prefs.UpDownPushDetected = IsOff;	// WbMn
	prefs.prevCmdBtnIndex = NULL;		// WbMn
	prefs.numButtons = NULL;			// WbMn
	prefs.keyControlHandled = 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.OpenHwrKeyControlF == IsOn)
	{
		SysNotifyRegister (cardNo, dbID, sysNotifyEventDequeuedEvent,
					 &WbMnUpDownKeyEventPreHandle, WbMnPriority, (MemPtr)'WbMn');
	}

	if (prefs.MenuHwrKeyControlF == IsOn)
	{
		SysNotifyRegister (cardNo, dbID, sysNotifyEventDequeuedEvent,
					 &WbMmMenuKeyDownHandle, WbMmPriority, (MemPtr)'WbMm');
	}

	if (prefs.ToolbarHwrKeyControlF == IsOn)
	{
		SysNotifyRegister (cardNo, dbID, sysNotifyMenuCmdBarOpenEvent,
					 &WbMtCmdBarOpenHandle, WbMtPriority, (MemPtr)'WbMt');
	}

	ActivateTrapHack ();
}

#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;
	if (FrmGetControlValue (frmP, FrmGetObjectIndex (frmP, TSuiteMenuHwrKeyControlCheckbox)) == true)
		prefs->MenuHwrKeyControlF = IsOn; else prefs->MenuHwrKeyControlF = IsOff;
	if (FrmGetControlValue (frmP, FrmGetObjectIndex (frmP, TSuiteToolbarHwrKeyControlCheckbox)) == true)
		prefs->ToolbarHwrKeyControlF = IsOn; else prefs->ToolbarHwrKeyControlF = IsOff;
	if (FrmGetControlValue (frmP, FrmGetObjectIndex (frmP, TSuiteOpenHwrKeyControlCheckbox)) == true)
		prefs->OpenHwrKeyControlF = IsOn; else prefs->OpenHwrKeyControlF = 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);
	FrmSetControlValue (frmP, FrmGetObjectIndex (frmP, TSuiteMenuHwrKeyControlCheckbox), prefs->MenuHwrKeyControlF);
	FrmSetControlValue (frmP, FrmGetObjectIndex (frmP, TSuiteToolbarHwrKeyControlCheckbox), prefs->ToolbarHwrKeyControlF);
	FrmSetControlValue (frmP, FrmGetObjectIndex (frmP, TSuiteOpenHwrKeyControlCheckbox), prefs->OpenHwrKeyControlF);
}

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

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

//	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 TSuiteMenuHwrKeyControlInfGraphicButton:
				FrmAlert (MenuHwrKeyControlAlert);
				handled = true;
				break;

			case TSuiteToolbarHwrKeyControlInfGraphicButton:
				FrmAlert (ToolbarHwrKeyControlAlert);
				handled = true;
				break;

			case TSuiteOpenHwrKeyControlInfGraphicButton:
				FrmAlert (OpenHwrKeyControlAlert);
				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:
			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 'BlkS':
						BlkSEventDequedHandle (NtfyPrm);
						break;
					case 'WbMn':
						WbMnUpDownKeyEventPreHandle (NtfyPrm);
						break;
					case 'WbMm':
						WbMmMenuKeyDownHandle (NtfyPrm);
						break;
					case 'WbMt':
						WbMtCmdBarKeyDownHandle (NtfyPrm);
						break;
					case 'FTgl':
						FTglCmdBarKeyDownHandle (NtfyPrm);
						break;
					}
					break;

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

				case appFileCreator:
					switch ((UInt32)(NtfyPrm->userDataP))
					{
//					case 'WbMm':
//						break;
					case 'WbMt':
						WbMtCmdBarOpenedHandle (NtfyPrm);
						break;
					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);
}
