/* reportPanel.c 
 *
 *  defines the GUIFront characteristics of the reporting panel 
 */
  
#include <stdio.h>  
#include <intuition/gadgetclass.h>
#include <clib/asl_protos.h>
#include <libraries/asl.h>
#include "amiCheck.h"
#include "regGadget.h"
#include "dataBase.h"
#include "reportPanel.h"
#include <string.h>

#define MINROW	5
#define MAXROW	300
#define MINCOL	40
#define MAXCOL	300

/* prototypes */
BOOL ReportHandleGadget(struct IntuiMessage *);
void ReportInit(void);
BOOL ReportGoodbye(struct IntuiMessage *, reportSetting *);
BOOL ReportOutput(void);
void ReportCompact(entryNode *, char *);
void ReportNormal(entryNode *, char *, char *);
void ReportVerbose(entryNode *, char *, char *, char *);

BOOL genrep;
struct Window *repWin;
ExtErrorData ReportExtData;
GUIFront *repGUI;

reportSetting localrep;


STRPTR replabels[] =
{
	"Compact",
	"Normal",
	"Verbose",
	NULL,
};

struct TagItem  repcytags[] = {
	{GTCY_Labels,replabels},
	{TAG_DONE},
};

/* define gadgetspec */
GadgetSpec REPgadgetspecs[] = 
{
        {CHECKBOX_KIND,0,0,{0,0,0,0,"To _File", NULL, GID_REPTOFILE,         
                PLACETEXT_RIGHT}, NULL, GS_DefaultTags},

        {CHECKBOX_KIND,0,0,{0,0,0,0,"_Pad Blank Line", NULL, GID_REPBLANK,         
                PLACETEXT_RIGHT}, NULL, GS_DefaultTags},

	{CYCLE_KIND,0,0,{0,0,0,0,"Report _Style", NULL, GID_REPSTYLE,
		PLACETEXT_LEFT}, repcytags, GS_DefaultTags},

        {CHECKBOX_KIND,0,0,{0,0,0,0,"_Include Summary & Info", NULL, GID_REPSUMMARY,         
                PLACETEXT_RIGHT}, NULL, GS_DefaultTags},

        {INTEGER_KIND,0,0,{0,0,0,0,"Cols Per _Line", NULL, GID_REPCOLS,         
                PLACETEXT_LEFT}, NULL, GS_DefaultTags},

        {INTEGER_KIND,0,0,{0,0,0,0,"_Rows Per Page", NULL, GID_REPROWS,         
                PLACETEXT_LEFT},NumBorder, GS_DefaultTags},

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

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

        {CHECKBOX_KIND,0,0,{0,0,0,0,"_Transaction State", NULL, GID_REPSTATE,         
                PLACETEXT_RIGHT}, NULL, GS_DefaultTags},

};

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


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

   GUIL_HorizGroup, 2,
	GUIL_Flags, GUILF_PropShare | GUILF_EqualHeight,
	GUIL_FrameType, GUILFT_Recess,

	GUIL_VertGroup, 1,  
		GUIL_Flags, GUILF_LabelAlign | GUILF_EqualWidth,
		GUIL_GadgetSpecID, GID_REPSTYLE,
		GUIL_GadgetSpecID, GID_REPCOLS,
		GUIL_GadgetSpecID, GID_REPROWS,

	TAG_DONE,

	GUIL_VertGroup, 1,
		GUIL_Flags, GUILF_LabelAlign,

		GUIL_GadgetSpecID, GID_REPTOFILE,
		GUIL_GadgetSpecID, GID_REPSUMMARY,
		GUIL_GadgetSpecID, GID_REPSTATE,
		GUIL_GadgetSpecID, GID_REPBLANK,
			
	TAG_DONE,
   
    TAG_DONE,
    
    GUIL_HorizGroup,1,
        GUIL_Flags, GUILF_EqualSize | GUILF_EqualWidth,
        
           GUIL_GadgetSpecID, GID_REPOK,
	   GUIL_GadgetSpecID, GID_REPCANCEL,
           
    TAG_DONE,   
           
TAG_DONE,
};


/****************************************************
* ReportGUI ()
*
*	Creates the GUI for the stat panel.
*****************************************************/
void  ReportGUI(void)
{
 BOOL done = FALSE;
 BOOL reply;
 ULONG signal;
     
   AmiLock();

 
		GF_SetGUIAttr(repGUI, GUI_OpenGUI, TRUE, TAG_DONE);
	  	GF_GetGUIAttr(repGUI, GUI_Window, &repWin, TAG_DONE);

 		ReportInit();

                /* 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))
                    {
			reply = TRUE;
                        switch (imsg->Class) {
				case IDCMP_REFRESHWINDOW:
					RegRefresh(TRUE);
					break;

                                case IDCMP_CLOSEWINDOW:
					done = TRUE;
                                        break;

				case IDCMP_GADGETUP:
					reply = FALSE;
					done=ReportHandleGadget(imsg);
					break;

				case IDCMP_RAWKEY:
					AmiHelpKey(imsg,REPORT_PANEL);
					break;
                        }
                                     
                              
	 		if (reply)
				GF_ReplyIMsg(imsg);
                    }
                }

   GF_SetGUIAttr(repGUI, GUI_OpenGUI, FALSE, TAG_DONE);               
   if (genrep) {
	GF_LockGUI(repGUI);
	if (!ReportOutput())
		AmiAnnounce("Printer Failure.\nOperation cancelled.");
	GF_UnlockGUI(repGUI);
   }
   AmiUnlock();
}

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

 switch (gad->GadgetID) {
	
	case GID_REPTOFILE:
		localrep.tofile = code;
		break;

	case GID_REPSTATE:
		localrep.state = code;
		break;

	case GID_REPSUMMARY:
		localrep.summary = code;
		break;

	case GID_REPBLANK:
		localrep.padline = code;
		break;

	case GID_REPSTYLE:
		localrep.style = code;
		break;

	case GID_REPROWS:
 		localrep.rows = (UWORD)((struct StringInfo*)(REP_ReportSpecs[GID_REPROWS]->gs_Gadget)->
				SpecialInfo)->LongInt;

		if (localrep.rows < MINROW || localrep.rows > MAXROW) {
			DisplayBeep(repWin->WScreen);
			DataAnnounce(repGUI, "Illegal rows per page");
			GF_ReplyIMsg(imsg);
			DataSitNSpin(REP_ReportSpecs[GID_REPROWS]->gs_Gadget,repWin);
  			return (done);
		}
		break;

	case GID_REPCOLS:
 		localrep.cols = (UWORD)((struct StringInfo*)(REP_ReportSpecs[GID_REPCOLS]->gs_Gadget)->
				SpecialInfo)->LongInt;

		if (localrep.cols < MINCOL || localrep.cols > MAXCOL) {
			DisplayBeep(repWin->WScreen);
			DataAnnounce(repGUI, "Illegal columns per line");
			GF_ReplyIMsg(imsg);
			DataSitNSpin(REP_ReportSpecs[GID_REPCOLS]->gs_Gadget,repWin);
  			return (done);
		}
		break;

	case GID_REPCANCEL:
		done = TRUE;
		break;

	case GID_REPOK:
		if (ReportGoodbye(imsg, &localrep)) {
			done = TRUE;	
			memcpy(&reportControl,&localrep,sizeof(reportSetting));
			amiChangedItems = TRUE;
			genrep = TRUE;
		}
		else return (FALSE);
		break;
 }

 GF_ReplyIMsg(imsg);
 return (done);
}

/****************************************************
* ReportInit()
*
*	Set up some globals
*****************************************************/
void ReportInit(void)
{

 genrep = FALSE;

 memcpy(&localrep,&reportControl,sizeof(reportSetting));

 GF_SetGadgetAttrs (repGUI, REP_ReportSpecs[GID_REPTOFILE]->gs_Gadget,
	GTCB_Checked,localrep.tofile,
	TAG_DONE);

 GF_SetGadgetAttrs (repGUI, REP_ReportSpecs[GID_REPSUMMARY]->gs_Gadget,
	GTCB_Checked,localrep.summary,
	TAG_DONE);

 GF_SetGadgetAttrs (repGUI, REP_ReportSpecs[GID_REPBLANK]->gs_Gadget,
	GTCB_Checked,localrep.padline,
	TAG_DONE);

 GF_SetGadgetAttrs (repGUI, REP_ReportSpecs[GID_REPSTYLE]->gs_Gadget,
		GTCY_Active,localrep.style,
		TAG_DONE);

 GF_SetGadgetAttrs (repGUI, REP_ReportSpecs[GID_REPROWS]->gs_Gadget,
			GTIN_Number, localrep.rows,
			TAG_DONE); 

 GF_SetGadgetAttrs (repGUI, REP_ReportSpecs[GID_REPCOLS]->gs_Gadget,
			GTIN_Number, localrep.cols,
			TAG_DONE);

 GF_SetGadgetAttrs (repGUI, REP_ReportSpecs[GID_REPSTATE]->gs_Gadget,
	GTCB_Checked,localrep.state,
	TAG_DONE);

}

/****************************************************
* ReportGoodbye()
*
*	Capture strings
*****************************************************/
BOOL ReportGoodbye(struct IntuiMessage *imsg, reportSetting *temp)
{
 UWORD val;

 val = (UWORD)((struct StringInfo*)(REP_ReportSpecs[GID_REPROWS]->gs_Gadget)->SpecialInfo)->LongInt;
 if (val < MINROW || val > MAXROW) {
	DisplayBeep(repWin->WScreen);
	DataAnnounce(repGUI, "Illegal rows per page");
	GF_ReplyIMsg(imsg);
	DataSitNSpin(REP_ReportSpecs[GID_REPROWS]->gs_Gadget,repWin);
	return (FALSE);
 }
 else temp->rows = val;

 val = (UWORD)((struct StringInfo*)(REP_ReportSpecs[GID_REPCOLS]->gs_Gadget)->SpecialInfo)->LongInt;
 if (val < MINCOL || val > MAXCOL) {
	DisplayBeep(repWin->WScreen);
	DataAnnounce(repGUI, "Illegal columns per line");
	GF_ReplyIMsg(imsg);
	DataSitNSpin(REP_ReportSpecs[GID_REPCOLS]->gs_Gadget,repWin);
 	return (FALSE);
 }
 else temp->cols = val;
 
 return (TRUE);
}


/***********************************************************
* ReportOutput()
*
*	Actual printing of data
************************************************************/
BOOL ReportOutput(void)
{ 
 char fname[100];
 char tempstr[200],tempAmnt[AMNTSIZE+1];
 char outstr[3][MAXCOL+1];
 int r,x;
 FILE *temp;
 amountType zero=0;
 balanceType amnt;
 filterNode *filt = (filterNode *)filtered.mlh_Head;
  
 if (filtered.mlh_TailPred == &filtered)
	return FALSE;

 if (reportControl.tofile) {
	/* asl save req */
	if (!(AmiGetFile(repGUI,reportASL,fname,100)))
		return FALSE;
 }
 else  sprintf(fname,"prt:");
	
 if ((temp = fopen(fname,"w")) == NULL) {
		AmiAnnounce("Trouble generating report.");
		return FALSE;
 }

 /* fill temp file up */
 r = 0;
 DataInitBal(DEPOSITTYPE,&zero,&amnt);

 /* include account info */
 if (reportControl.summary) {
	sprintf(tempstr,"\nAccount Holder: %s\n",usrAccount.holder);
 	if (fprintf(temp,tempstr) != strlen(tempstr)) {
		fclose(temp);
		return (FALSE);
	}
		

 	sprintf(tempstr,"Institution   : %s\n",usrAccount.bank);
 	if (fprintf(temp,tempstr) != strlen(tempstr)) {
		fclose(temp);
		return (FALSE);
	}

 	sprintf(tempstr,"Account#      : %s\n",usrAccount.accnt);
 	if (fprintf(temp,tempstr) != strlen(tempstr)) {
		fclose(temp);
		return (FALSE);
	}

 	if (fprintf(temp,"\n") != strlen("\n")) {
		fclose(temp);
		return (FALSE);
	}
 	r += 5;
 }

 do {
	/* by style, output columns */
	switch (reportControl.style) {
		case 0:
			ReportCompact(filt->entry,outstr[0]);
			break;
		case 1:
			ReportNormal(filt->entry,outstr[0], outstr[1]);
			break;
		case 2:
			ReportVerbose(filt->entry,outstr[0], outstr[1], outstr[2]);
			break;
	}

	if (!(filt->entry->flags & VOIDED)) {
		DataAddBal(filt->entry->type,&filt->entry->amount,&amnt);
	}

	if (r+reportControl.style+2 >= reportControl.rows && !reportControl.tofile) {
		if (fprintf(temp,"\f\n") != strlen("\f\n")) {
			fclose(temp);
			return (FALSE);
		}
		r = 1;
	}

	for (x=0;x<=reportControl.style;x++) {
		if (fprintf(temp,"%s",outstr[x]) != strlen(outstr[x])) {
			fclose(temp);
			return (FALSE);
		}
	}

	r += reportControl.style + 1;

	if (reportControl.padline && r < reportControl.rows-1){
		if (fprintf(temp,"\n") != strlen("\n")) {
			fclose(temp);
			return (FALSE);
		}
		r++;
	}
	
	filt = (filterNode *)DataGetNext((struct List *)&filtered,(struct Node *)filt);
 } while (filt != NULL);
 
 /* fill in summary */ 
 if (reportControl.summary) {
	if (r + 4 > reportControl.rows-1)
		if (fprintf(temp,"\f\n") != strlen("\f\n")) {
			fclose(temp);
			return (FALSE);
		}

	if (fprintf(temp,"\n") != strlen("\n")) {
		fclose(temp);
		return (FALSE);
	}

	DataBuildBal(usrAccount.decimal,&amnt,tempAmnt);
	sprintf(tempstr,"Report Balance   : %s\n",tempAmnt);
	if (fprintf(temp,tempstr) != strlen(tempstr)) {
		fclose(temp);
		return (FALSE);
	}

	DataBuildBal(usrAccount.decimal,&amntState.currAmnt,tempAmnt);
 	sprintf(tempstr,"Current Balance  : %s\n",tempAmnt);
	if (fprintf(temp,tempstr) != strlen(tempstr)) {
		fclose(temp);
		return (FALSE);
	}

	DataBuildBal(usrAccount.decimal,&amntState.stateAmnt,tempAmnt);
	sprintf(tempstr,"Statement Balance: %s\n",tempAmnt);
	if (fprintf(temp,tempstr) != strlen(tempstr)) {
		fclose(temp);
		return (FALSE);
	}
 }

 fclose(temp);

 /* output icon */
 if (reportControl.tofile) 
	DataAttachIcon(iconPath,"AC_Report",fname);

 return (TRUE);
}

/**************************************************************
* ReportCompact()
*
*	Fills in string for compact output
**************************************************************/
void ReportCompact(entryNode *en, char *line)
{
 char type[11];
 char tempAmnt[AMNTSIZE+1];
 char amnt[13];
 char date[DATESIZE+1];
 char name[MAXCOL]; 
 char flags[7];
 int x,y, namesize;

 switch (en->type) {
	case CHECKTYPE:
		sprintf(type,"%05d     ",en->check);
		break;

 	case DEPOSITTYPE:
		sprintf(type,"Deposit   ");
		break;

	case WITHDRAWALTYPE:
		sprintf(type,"Withdrawal");
		break;

 }

 if (reportControl.state) {
 	sprintf(flags,"[    ]");
 	if (en->flags & VOIDED)
		flags[1]='V';
 	if (en->flags & TAXDEDUCT)
		flags[2]='T';
 	if (en->flags & CLEARED)
		flags[3]='C';
	if (en->flags & RECONCILED)
		flags[4]='R';
 }
 else flags[0] = NULL;

 DataBuildAmnt(TRUE,&en->amount,tempAmnt);
 sprintf(amnt,"%c% 9s%c\n",(en->type != DEPOSITTYPE)?'(':' ',tempAmnt,
				(en->type != DEPOSITTYPE)?')':' '
				);
 DataBuildDate(&en->date,date);
 namesize = reportControl.cols - (strlen(type)+strlen(date)+strlen(flags)+strlen(amnt));
 strncpy(name,en->name,namesize);
 y = strlen(name);
 if (y < namesize) {
	for (x=0;x< (namesize-y)-1; x++)
		name[x+y] = '.';

	name[x+y]=NULL;
 }
 else name[namesize-1] = NULL;

 bzero(line,reportControl.cols);
 sprintf(line,"%s %s %s%s%s",type, date, name, flags, amnt); 
}

/****************************************************************************************
* ReportNormal()
*
*	two line entries
*****************************************************************************************/
void ReportNormal(entryNode *en, char *line1, char *line2)
{
 
 ReportCompact(en,line1);
 bzero(line2,reportControl.cols);

 sprintf(line2,"                Memo: ");

 strncat(line2,en->memo,reportControl.cols-strlen(line2)-11 );
 strcat(line2,"\n");
}

/****************************************************************************************
* ReportVerbose()
*
*	three line entries
*****************************************************************************************/
void ReportVerbose(entryNode *en, char *line1, char *line2, char *line3)
{
 char filler[30];
 char cat[CATNAMESIZE];
 char tempstr[MAXCOL];
 int x,y;

 ReportNormal(en,line1,line2);
 sprintf(filler,"            Category: ");

 bzero(cat,CATNAMESIZE);
 strcpy(cat,en->category);
 y = strlen(cat);
 if (y < CATNAMESIZE-1) {
 	for (x=y;x<CATNAMESIZE-1;x++)  
		cat[x]=' ';
	cat[x] = NULL;
 }


 sprintf(tempstr,"%s%s %s\n",filler,cat,(en->flags&RECONCILED)?"RECONCILED":"");

 bzero(line3,reportControl.cols); 
 strncpy(line3,tempstr,reportControl.cols-10);
 line3[strlen(line3)-1] = '\n';
}
