/* acctPanel.c 
 *
 *  defines the GUIFront characteristics of the acct account panel 
 */
  
#include <stdio.h>  
#include <intuition/gadgetclass.h>
#include "amiCheck.h"
#include "regGadget.h"
#include "acctPanel.h"
#include "dataBase.h"
#include <string.h>

/* prototypes */
BOOL AcctPHandleGadget(struct IntuiMessage *);
BOOL AcctPHandleGadgetDown(struct IntuiMessage *);
void AcctInit(BOOL);
void AcctSlideDecimal(ULONG);
void AcctConvAmnt(ULONG);
BOOL AcctGoodbye(struct IntuiMessage *, accntState *);

BOOL acctretval,newacct;
ExtErrorData AcctExtData;
GUIFront *acctGUI;
accntState tempAcct;
struct Window *acctWin;

struct TagItem decimalTags[] = {
	GTSL_Min, 0,
	GTSL_Max, MAXDECIMAL,
	GTSL_Level, 2,
	GA_Immediate, TRUE,
	TAG_DONE,
};

/* define gadgetspec */
GadgetSpec ACPgadgetspecs[] = 
{

	{STRING_KIND,20,1,{0,0,0,0,"Account _Number",NULL, GID_ACPACCT,
		PLACETEXT_LEFT}, strNameTags, GS_DefaultTags | GS_NoHeightExtend},

	{STRING_KIND,20,1,{0,0,0,0,"_Bank Name",NULL, GID_ACPBANK,
		PLACETEXT_LEFT}, strNameTags, GS_DefaultTags| GS_NoHeightExtend},

	{INTEGER_KIND,CHECKSIZE,1,{0,0,0,0,"C_heck Number",NULL, GID_ACPCHECK,
		PLACETEXT_LEFT}, strCheckTags, GS_DefaultTags| GS_NoHeightExtend},

	{STRING_KIND,DATESIZE,1,{0,0,0,0,"Date O_pened",NULL, GID_ACPOPEN,
		PLACETEXT_LEFT}, strDateTags, GS_DefaultTags| GS_NoHeightExtend},

	{STRING_KIND,DATESIZE,1,{0,0,0,0,"Date C_losed",NULL, GID_ACPCLOSE,
		PLACETEXT_LEFT}, strDateTags, GS_DefaultTags| GS_NoHeightExtend},

	{STRING_KIND,AMNTSIZE,1,{0,0,0,0,"Initial _Deposit",NULL, GID_ACPBALANCE,
		PLACETEXT_LEFT}, strAmntTags, GS_DefaultTags| GS_NoHeightExtend},

	{STRING_KIND,20,1,{0,0,0,0,"Account _Holder",NULL, GID_ACPHOLDER,
		PLACETEXT_LEFT}, strNameTags, GS_DefaultTags| GS_NoHeightExtend},

	{CHECKBOX_KIND,0,0,{0,0,0,0,"Clo_sed",NULL, GID_ACPCLOSED,
		PLACETEXT_LEFT}, NULL, GS_DefaultTags},

        {BUTTON_KIND,0,0,{0,0,0,0,"_OK", NULL, GID_ACPOK,         
                PLACETEXT_IN}, NULL, GS_DefaultTags},

        {BUTTON_KIND,0,0,{0,0,0,0,"_Cancel", NULL, GID_ACPCANCEL,        
                PLACETEXT_IN}, NULL, GS_DefaultTags},

	{INTEGER_KIND,0,0,{0,0,0,0,"Decima_l",NULL,GID_ACPDECIMAL,
		PLACETEXT_LEFT},TxtInt,GS_DefaultTags},
	
	{SLIDER_KIND,0,0,{0,0,0,0,NULL,NULL,GID_ACPDECSLIDE,
		PLACETEXT_LEFT},decimalTags,GS_DefaultTags},
};

/* set up array of pointers to our specs */
GadgetSpec *ACP_AcctSpecs[] =
{
        &ACPgadgetspecs[0],
        &ACPgadgetspecs[1],
        &ACPgadgetspecs[2],
        &ACPgadgetspecs[3],
        &ACPgadgetspecs[4],
        &ACPgadgetspecs[5],
        &ACPgadgetspecs[6],
        &ACPgadgetspecs[7],
        &ACPgadgetspecs[8],
	&ACPgadgetspecs[9],
        &ACPgadgetspecs[10],
	&ACPgadgetspecs[11],
       	NULL,
};


/* define the layout of this panel */
ULONG ACP_AcctPanel[] =
{
   GUIL_Flags, GUILF_PropShare | GUILF_EqualWidth,

   GUIL_HorizGroup, 1,
        GUIL_Flags, GUILF_PropShare | GUILF_EqualHeight,
	GUIL_FrameType, GUILFT_Recess,
        
	GUIL_VertGroup, 1,
		GUIL_Flags, GUILF_LabelAlign | GUILF_PropShare | GUILF_EqualWidth,
		GUIL_FrameType, GUILFT_Ridge,
		GUIL_FrameHeadline, "Bank Information",

		GUIL_GadgetSpecID, GID_ACPHOLDER,
		GUIL_GadgetSpecID, GID_ACPACCT,
		GUIL_GadgetSpecID, GID_ACPBANK,
		GUIL_GadgetSpecID, GID_ACPOPEN,
	TAG_DONE,
    
	GUIL_VertGroup, 1,
		GUIL_Flags, GUILF_PropShare | GUILF_EqualWidth,

		GUIL_VertGroup, 1,
			GUIL_Flags, GUILF_LabelAlign | GUILF_EqualWidth,
			GUIL_FrameType, GUILFT_Ridge,
			GUIL_FrameHeadline, "Account Defaults",
		
			GUIL_GadgetSpecID, GID_ACPCHECK,
			GUIL_GadgetSpecID, GID_ACPBALANCE,

			GUIL_HorizGroup,0,
				GUIL_GadgetSpecID, GID_ACPDECIMAL,
				GUIL_GadgetSpecID, GID_ACPDECSLIDE,
			TAG_DONE,

		TAG_DONE,

		GUIL_VertGroup,1,
			GUIL_Flags, GUILF_LabelAlign | GUILF_EqualWidth,
			GUIL_FrameType, GUILFT_Recess,

			GUIL_GadgetSpecID, GID_ACPCLOSED,
			GUIL_GadgetSpecID, GID_ACPCLOSE,
		TAG_DONE,

	TAG_DONE, 
    TAG_DONE,
    
    GUIL_HorizGroup,1,
        GUIL_Flags, GUILF_EqualSize | GUILF_EqualWidth,
        
           GUIL_GadgetSpecID, GID_ACPOK,
           GUIL_GadgetSpecID, GID_ACPCANCEL,
           
    TAG_DONE,   
           
TAG_DONE,
};


/****************************************************
* AcctGUI ()
*
*	Creates the GUI for the sort panel.
*****************************************************/
BOOL AcctGUI(char *str, BOOL newone)
{
 BOOL done = FALSE;
 BOOL replyval;
 ULONG signal;
     
   AmiLock();
 
		
		GF_SetGUIAttr(acctGUI,GUI_OpenGUI,TRUE,TAG_DONE);
	 	/* grab window */
 		GF_GetGUIAttr(acctGUI,GUI_Window,&acctWin,TAG_DONE);
		SetWindowTitles(acctWin,str,(UBYTE *)-1);

		AcctInit(newone);

                /* Process input events */
                while (!done)
                {
                    struct IntuiMessage *imsg;

                    /* Wait for an event to occur */

                    signal = GF_Wait(guiapp,AmigaGuideSignal(agc));
		    if (signal & AmigaGuideSignal(agc)) {
			AmiHelpMsg();
			continue;
		    }

                    /* We only bother to listen for CLOSEWINDOW events.
                     * Of course, in a real application, you would be
                     * examining the Class field for IDCMP_GADGETUP
                     * messages and act accordingly.
                     */

                    while (imsg = GF_GetIMsg(guiapp))
                    {
			replyval = TRUE;
                        switch (imsg->Class) {
				case IDCMP_REFRESHWINDOW:
					RegRefresh(TRUE);
					break;

                                case IDCMP_CLOSEWINDOW:
					done = TRUE;
                                        break;

	                        case IDCMP_GADGETDOWN:
					replyval = FALSE;
					done=AcctPHandleGadgetDown(imsg);
					break;
				
				case IDCMP_MOUSEMOVE:
					AcctSlideDecimal(imsg->Code);
					break;

				case IDCMP_GADGETUP:
					replyval = FALSE;
					done=AcctPHandleGadget(imsg);
					break;
			
				case IDCMP_RAWKEY:
					AmiHelpKey(imsg,ACCOUNT_PANEL);
					break;
                        }
                                     
                              
                        if (replyval) GF_ReplyIMsg(imsg);
                    }
                }


   GF_SetGUIAttr(acctGUI, GUI_OpenGUI, FALSE, TAG_DONE);            
   AmiUnlock();

 return (acctretval);
}


/**************************************************
* AcctSlideDecimal()
*
* 	control decimal slide gadget
***************************************************/
void AcctSlideDecimal(ULONG decim)
{
 AcctConvAmnt(decim);
 tempAcct.decimal = decim;

 /* update decimal */
 GF_SetGadgetAttrs(acctGUI, ACP_AcctSpecs[GID_ACPDECIMAL]->gs_Gadget,
	GTIN_Number, decim,
	TAG_DONE);
}

/***************************************************
* AcctPHandleGadgetDown()
*
*	Handles gadget down events for this panel
****************************************************/
BOOL  AcctPHandleGadgetDown(struct IntuiMessage *imsg)
{
 BOOL done = FALSE;
 struct Gadget *gad =  (struct Gadget *)(imsg->IAddress);
 UWORD code = imsg->Code;

 switch (gad->GadgetID) {

	case GID_ACPDECSLIDE:
		AcctSlideDecimal(code);
		break;
 }

 GF_ReplyIMsg(imsg);
 return done;	
}

/***************************************************
* AcctPHandleGadget()
*
*	Handles gadget events for this panel
****************************************************/
BOOL  AcctPHandleGadget(struct IntuiMessage *imsg)
{
 BOOL done = FALSE;
 struct Gadget *gad =  (struct Gadget *)(imsg->IAddress);
 UWORD code = imsg->Code;
 amountType zero=0;
 balanceType origbal;
 ULONG decim;
 char newamntstr[AMNTSIZE];
 char newdatestr[DATESIZE];
 
 switch (gad->GadgetID) {

	case GID_ACPHOLDER:
		strncpy(tempAcct.holder,((struct StringInfo *)gad->SpecialInfo)->Buffer, STRINGSIZE);
		break;

	case GID_ACPACCT:
		strncpy(tempAcct.accnt,((struct StringInfo *)gad->SpecialInfo)->Buffer, STRINGSIZE);
		break;

	case GID_ACPBANK:
		strncpy(tempAcct.bank,((struct StringInfo *)gad->SpecialInfo)->Buffer, STRINGSIZE);
		break;

	case GID_ACPCHECK:
		tempAcct.checknumber = (UWORD)((struct StringInfo*)gad->SpecialInfo)->LongInt;
		break;

	case GID_ACPBALANCE:
		/* special case return early.... activated gadget */
		decim = usrAccount.decimal;
		usrAccount.decimal = tempAcct.decimal;
		if (!DataVerifyAmnt(((struct StringInfo*)gad->SpecialInfo)->Buffer,newamntstr) ) {
			usrAccount.decimal = decim;
			DisplayBeep(acctWin->WScreen);
			DataAnnounceAmount(acctGUI);
			GF_ReplyIMsg(imsg);
			DataSitNSpin(ACP_AcctSpecs[GID_ACPBALANCE]->gs_Gadget,acctWin);
			return (done);
		}
 		else {
			DataStoreAmnt(&tempAcct.beginAmount,newamntstr );
			GF_SetGadgetAttrs(acctGUI,ACP_AcctSpecs[GID_ACPBALANCE]->gs_Gadget,
				GTST_String,newamntstr,
				TAG_DONE);
			usrAccount.decimal = decim;
		}	
		break;

	case GID_ACPOPEN:
		/* special case return early.... activated gadget */
		if (!DataVerifyDate(((struct StringInfo*)gad->SpecialInfo)->Buffer,newdatestr) ) {
			DisplayBeep(acctWin->WScreen);
			DataAnnounceDate(acctGUI);
			GF_ReplyIMsg(imsg);
			DataSitNSpin(ACP_AcctSpecs[GID_ACPOPEN]->gs_Gadget,acctWin);
			return (done);
		}
 		else {
			DataStoreDate(&tempAcct.openDate,newdatestr );
			GF_SetGadgetAttrs(acctGUI,ACP_AcctSpecs[GID_ACPOPEN]->gs_Gadget,
				GTST_String,newdatestr,
				TAG_DONE);
		}
		break;
	
	case GID_ACPCLOSE:
		/* special case return early.... activated gadget */
		if (!DataVerifyDate(((struct StringInfo*)gad->SpecialInfo)->Buffer,newdatestr) ) {
			DisplayBeep(acctWin->WScreen);
			DataAnnounceDate(acctGUI);
			GF_ReplyIMsg(imsg);
			DataSitNSpin(ACP_AcctSpecs[GID_ACPCLOSE]->gs_Gadget,acctWin);
			return (done);
		}
 		else {
			DataStoreDate(&tempAcct.closeDate,newdatestr );
			GF_SetGadgetAttrs(acctGUI,ACP_AcctSpecs[GID_ACPCLOSE]->gs_Gadget,
				GTST_String,newdatestr,
				TAG_DONE);
		}
		break;

	case GID_ACPCLOSED:
		tempAcct.closed = code;
		GF_SetGadgetAttrs (acctGUI, ACP_AcctSpecs[GID_ACPCLOSE]->gs_Gadget,
			GA_Disabled, !tempAcct.closed,
			TAG_DONE);
		break;

	case GID_ACPDECIMAL:
		decim = ((struct StringInfo*)gad->SpecialInfo)->LongInt;
		if (decim > MAXDECIMAL) {
			DisplayBeep(acctWin->WScreen);
			DataAnnounce(acctGUI, "Too many decimal places");
			GF_ReplyIMsg(imsg);
			DataSitNSpin(ACP_AcctSpecs[GID_ACPDECIMAL]->gs_Gadget,acctWin);
			return (done);
		}
		else {
	
			/* update in real-time our displayed amount for the user's
				feedback */
			AcctConvAmnt(decim);
			tempAcct.decimal = decim;

			/* update slider too */
			GF_SetGadgetAttrs(acctGUI, ACP_AcctSpecs[GID_ACPDECSLIDE]->gs_Gadget,
				GTSL_Level, decim,
				TAG_DONE);
		}
		break;

	case GID_ACPCANCEL:
		done = TRUE;
		break;
                         
	case GID_ACPOK:
		if (AcctGoodbye(imsg, &tempAcct)) {
			amiChangedItems = TRUE;

			/* reflect this in the current balance */
			if (newacct) 
				DataInitBal(DEPOSITTYPE,&zero,&origbal);
			else  {
				memcpy(&origbal,&amntState.currAmnt,sizeof(balanceType));
				DataAddBal(WITHDRAWALTYPE,&usrAccount.beginAmount,&origbal);
			}

			DataAddBal(DEPOSITTYPE,&tempAcct.beginAmount,&origbal);
			memcpy(&amntState.currAmnt,&origbal,sizeof(balanceType));
			memcpy(&usrAccount, &tempAcct, sizeof(accntState));
			acctretval = TRUE;
			done = TRUE;
		}
		else return (FALSE);
 		break;
 }

 GF_ReplyIMsg(imsg);
 return (done);
}

/****************************************************
* AcctInit()
*
*	Set up some globals
*****************************************************/
void AcctInit(BOOL newone)
{
 char strdate[DATESIZE];
 char stramnt[AMNTSIZE];
 UBYTE decim = usrAccount.decimal;

 /* grab window */
 GF_GetGUIAttr(acctGUI,GUI_Window,&acctWin,TAG_DONE);

 acctretval = FALSE;
 newacct = newone;
 if (newone) {
	usrAccount.decimal = 2;
       	memset(&tempAcct,0,sizeof(accntState));
	tempAcct.checknumber = 1;
	tempAcct.decimal = 2;
	memcpy(&tempAcct.openDate,&currDate,sizeof(dateType));
	memcpy(&tempAcct.closeDate,&currDate,sizeof(dateType));
 }
 else  	memcpy(&tempAcct, &usrAccount,sizeof(accntState));

 GF_SetGadgetAttrs (acctGUI, ACP_AcctSpecs[GID_ACPBANK]->gs_Gadget,
	GTST_String, tempAcct.bank,
	TAG_DONE);

 GF_SetGadgetAttrs (acctGUI, ACP_AcctSpecs[GID_ACPACCT]->gs_Gadget,
	GTST_String, tempAcct.accnt,
	TAG_DONE);

 GF_SetGadgetAttrs (acctGUI, ACP_AcctSpecs[GID_ACPHOLDER]->gs_Gadget,
	GTST_String, tempAcct.holder,
	TAG_DONE);

 DataBuildAmnt(TRUE,&tempAcct.beginAmount,stramnt);
 GF_SetGadgetAttrs (acctGUI, ACP_AcctSpecs[GID_ACPBALANCE]->gs_Gadget,
	GTST_String,stramnt,
	TAG_DONE);

 DataBuildDate(&tempAcct.openDate,strdate);
 GF_SetGadgetAttrs (acctGUI, ACP_AcctSpecs[GID_ACPOPEN]->gs_Gadget,
	GTST_String,strdate,
	TAG_DONE);

 GF_SetGadgetAttrs (acctGUI, ACP_AcctSpecs[GID_ACPCLOSED]->gs_Gadget,
	GTCB_Checked, tempAcct.closed,
	TAG_DONE);

 GF_SetGadgetAttrs (acctGUI, ACP_AcctSpecs[GID_ACPCHECK]->gs_Gadget,
	GTIN_Number, tempAcct.checknumber,
	TAG_DONE);

 DataBuildDate(&tempAcct.closeDate,strdate);
 GF_SetGadgetAttrs (acctGUI, ACP_AcctSpecs[GID_ACPCLOSE]->gs_Gadget,
	GTST_String,strdate,
	GA_Disabled, !tempAcct.closed,
	TAG_DONE);

 GF_SetGadgetAttrs (acctGUI, ACP_AcctSpecs[GID_ACPDECIMAL]->gs_Gadget,
	GTIN_Number, tempAcct.decimal,
	GA_Disabled, !newone,
	TAG_DONE);

 GF_SetGadgetAttrs (acctGUI, ACP_AcctSpecs[GID_ACPDECSLIDE]->gs_Gadget,
	GTSL_Level, tempAcct.decimal,
	GA_Disabled, !newone,
	TAG_DONE);

 if (newone) usrAccount.decimal = decim;
}

/*********************************************************
* AcctGoodbye()
*
*	grabs strings
**********************************************************/
BOOL AcctGoodbye(struct IntuiMessage *imsg, accntState *temp)
{
 char *grab;
 char newdatestr[DATESIZE+1];
 char newamntstr[AMNTSIZE+1];
 ULONG decim;

 /* check for "special" cases */
 decim = usrAccount.decimal;
 usrAccount.decimal = tempAcct.decimal;
 grab = ((struct StringInfo *)(ACP_AcctSpecs[GID_ACPBALANCE]->gs_Gadget)->SpecialInfo)->Buffer;
 if (!DataVerifyAmnt(grab,newamntstr) ) {
	DisplayBeep(acctWin->WScreen);
	DataAnnounceAmount(acctGUI);
	GF_ReplyIMsg(imsg);
	DataSitNSpin(ACP_AcctSpecs[GID_ACPBALANCE]->gs_Gadget,acctWin);
	usrAccount.decimal = decim;
	return (FALSE);
 }
 else {
	DataStoreAmnt(&temp->beginAmount,newamntstr );
	usrAccount.decimal = decim;
 }	

 grab = ((struct StringInfo *)(ACP_AcctSpecs[GID_ACPOPEN]->gs_Gadget)->SpecialInfo)->Buffer;
 if (!DataVerifyDate(grab,newdatestr) ) {
	DisplayBeep(acctWin->WScreen);
	DataAnnounceDate(acctGUI);
	GF_ReplyIMsg(imsg);
	DataSitNSpin(ACP_AcctSpecs[GID_ACPOPEN]->gs_Gadget,acctWin);
	return (FALSE);
 }
 else {
	DataStoreDate(&temp->openDate,newdatestr );
 }

if (temp->closed) {
 grab = ((struct StringInfo *)(ACP_AcctSpecs[GID_ACPCLOSE]->gs_Gadget)->SpecialInfo)->Buffer;
 if (!DataVerifyDate(grab,newdatestr) ) {
	DisplayBeep(acctWin->WScreen);
	DataAnnounceDate(acctGUI);
	GF_ReplyIMsg(imsg);
	DataSitNSpin(ACP_AcctSpecs[GID_ACPCLOSE]->gs_Gadget,acctWin);
	return (FALSE);
 }
 else {
	DataStoreDate(&temp->closeDate,newdatestr );
 }
}

 /* grab basic strings */
 temp->checknumber=(UWORD)((struct StringInfo*)(ACP_AcctSpecs[GID_ACPCHECK]->gs_Gadget)->SpecialInfo)->LongInt;

 grab = ((struct StringInfo *)(ACP_AcctSpecs[GID_ACPBANK]->gs_Gadget)->SpecialInfo)->Buffer;
 strncpy(temp->bank,grab, STRINGSIZE);

 grab = ((struct StringInfo *)(ACP_AcctSpecs[GID_ACPHOLDER]->gs_Gadget)->SpecialInfo)->Buffer;
 strncpy(temp->holder,grab, STRINGSIZE);

 grab = ((struct StringInfo *)(ACP_AcctSpecs[GID_ACPACCT]->gs_Gadget)->SpecialInfo)->Buffer;
 strncpy(temp->accnt,grab, STRINGSIZE);

 return (TRUE);
}

/**************************************************
* AcctConvAmnt()
*
*	Convert the begin amount to the new format
***************************************************/
void AcctConvAmnt(ULONG decim)
{
 balanceType temp;
 amountType zero = 0;
 char newamntstr[AMNTSIZE];	
 UBYTE type, olddecimal;

 olddecimal = usrAccount.decimal;
 usrAccount.decimal = tempAcct.decimal;

	/* obtain balance in our current form */
	DataInitBal(DEPOSITTYPE, &tempAcct.beginAmount, &temp);

	/* now convert it */
	DataBalConvert(&temp,tempAcct.decimal,decim);

 usrAccount.decimal = decim;
 	DataBalToAmnt(&temp,&type, &tempAcct.beginAmount);
 	DataBuildAmnt(TRUE,&tempAcct.beginAmount,newamntstr );
 usrAccount.decimal = olddecimal;

 GF_SetGadgetAttrs(acctGUI,ACP_AcctSpecs[GID_ACPBALANCE]->gs_Gadget,
	GTST_String,newamntstr,
	TAG_DONE);
}
