/* impexp.c 
 *
 *  defines the import/export filters
 */
#include <string.h>
#include <stdlib.h>
#include <exec/types.h>
#include <exec/lists.h>
#include <exec/nodes.h>
#include <exec/memory.h>
#include <stdio.h>  
#include <intuition/gadgetclass.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include "amiCheck.h"
#include "dataBase.h"
#include "regGadget.h"
#include "impexp.h"

extern char currFile[FILESIZE];
extern ULONG regValidRows, numRows;

/* prototypes */
void ImportAddEntry(entryNode *);

ULONG row;
filterNode *selFilt;
entryNode *selEntry;
static ULONG filtentries;

/*
 * ASCII filter
 */

/*********** the delimited format is as follows  ******************
*source  [comment (suggest account file name)]
*type	 ["withdrawal" | "deposit" | check number]
*amount	 [xxx.xx]
*date	 [mm/dd/yyyy]
*name	 [payee field or name]
*addr1
*addr2
*addr3
*memo	 [memo field]
*state    [Y|N][Y|N][Y|N] (ie: YNN, YYY) = cleared y/n, tax-deduct y/n, voided y/n
*category 0.00 [category]
*category 0.00 [category]
*... <as  many categories as needed> 
*
*Note that category may appear once, not at all, or as many times as 
*necessary. Non-unique categories are ignored for import. Currently,
*amicheck only supports one category, and if no category is assigned,
*the "none" category is assumed. 
*
*On import, the state flag "voided" is ignored for withdrawals and deposits
*(checks only).
*******************************************************************/
	
/**************************************************************
* ImportAscii()
*
*	Import an ascii file of transactions
***************************************************************/
BOOL ImportAscii(char *file)
{
BOOL ret = TRUE;
char cat_amnt[50],word[50], str[200],*data;
entryNode entry;
int x;
int state = 0;
FILE *infile;
struct Node *node;

 filtentries = 0;

 /* remember this bit later */
 row = selRow;
 if (row != -1) {
	selFilt = (filterNode *)DataOrd2Node((struct List *)&filtered,row);
	selEntry = selFilt->entry;
 }

 memset(&entry,0,sizeof(entryNode));
 entry.type = -1;

 strncpy(entry.category,"None",CATNAMESIZE);

 if ( (infile = fopen(file,"r")) == NULL)
	return (FALSE);

 while (fgets(str,200,infile)) {

	/* remove \n */
	if (strlen(str) > 0 && str[strlen(str)-1] == '\n')
		str[strlen(str)-1]=0;

	/* get control word */
	if ( (x=sscanf(str,"%s",word)) != 1) 
		continue;

	/* now get data string */
	data=strstr(str,word) + strlen(word);
	while (*data == ' ' && *data != 0)
		data++;
	
	/* remove starting line */
	if (state == 0) {
		if (stricmp(word,"Source") != 0) {
			ret = FALSE;
			break;
		}
		else {
			state++;
			continue;
		}
	}

newitem:
	/** ADD CURRENT ENTRY? **/
	if (state == 0x7fff ) {
		ImportAddEntry(&entry);
		memset(&entry,0,sizeof(entryNode));
		strncpy(entry.category,"None",CATNAMESIZE);
		entry.type = -1;
		state = 1;
	}

	/** TYPE **/
	if ( state == 1 ) {
		if (stricmp(word,"type") != 0) {
			ret = FALSE;
			break;
		}
		else {
			if (stricmp(data,"withdrawal") == 0)
				entry.type = WITHDRAWALTYPE;
			else if (stricmp(data,"deposit") == 0)
				entry.type = DEPOSITTYPE;
			else	{
				entry.type = CHECKTYPE;
				entry.check = (unsigned short)atoi(data);
			}
			state++;
			continue;
		}
	}

	/** AMOUNT **/
	if (state == 2 ) {
		if (stricmp(word,"amount") != 0) {
			ret = FALSE;
			break;
		}
		else  {
			DataStoreAmnt(&entry.amount,data);
			state++;
			continue;
		}
	}

	/** DATE **/
	if (state == 3) {
		if (stricmp(word,"date") != 0) {
			ret = FALSE;
			break;
		}
		else {
			DataStoreDate(&entry.date,data);
			state++;
			continue;
		}
	}

	/** NAME **/
	if (state == 4) {
		if (stricmp(word,"name") != 0) {
			ret = FALSE;
			break;
		}
		else {
			strncpy(entry.name,data,STRINGSIZE);
			state++;
			continue;
		}
	}

	/** ADDRESS **/
	if (state == 5) {
		if (stricmp(word,"addr1") != 0) {
			ret = FALSE;
			break;
		}
		else {
			state++;
			continue;
		}
	}
	if (state == 6) {
		if (stricmp(word,"addr2") != 0) {
			ret = FALSE;
			break;
		}
		else {
			state++;
			continue;
		}
	}
	if (state == 7) {
		if (stricmp(word,"addr3") != 0) {
			ret = FALSE;
			break;
		}
		else {
			state++;
			continue;
		}
	}

	/** MEMO **/
	if (state == 8 ) {
		if (stricmp(word,"memo") != 0) {
			ret = FALSE;
			break;
		}
		else {
			strncpy(entry.memo,data,STRINGSIZE);
			state++;
			continue;
		}
	}

	/** STATE **/
	if (state == 9 ) {
		if (stricmp(word,"state") != 0) {
			ret = FALSE;
			break;
		}
		else  {
			if (strlen(data) != 3)
				break;
			if (data[0] == 'Y')
				entry.flags |= CLEARED;
			if (data[1] == 'Y')
				entry.flags |= TAXDEDUCT;
			if (data[2] == 'Y' && entry.type == CHECKTYPE)
				entry.flags |= VOIDED;

			state++;
			continue;
		}
	}

	/** CATEGORIES **/
	if (state > 9) {
		if (stricmp(word,"category") != 0) {
			if (stricmp(word,"type") == 0) {
				state = 0x7fff;
				goto newitem;
			}
			else {
				ret = FALSE;
				break;
			}
		}
		else {
			/* pull out bogus amount */
			if ( (x=sscanf(data,"%s",cat_amnt)) != 1) 
				continue;

			/* verify it */
			if (stricmp(cat_amnt,"0.00") != 0) {
				ret = FALSE;
				break;
			}

			/* now move data string */
			data=strstr(data,cat_amnt) + strlen(cat_amnt);
			while (*data == ' ' && *data != 0)
				data++;

			/* TEST FOR CATEGORY EXISTANCE */
			if ( (node = DataFindName(&categories,data)) == NULL)
				strncpy(entry.category,"None",CATNAMESIZE);
			else	strncpy(entry.category,node->ln_Name,CATNAMESIZE);
			state++;
			continue;
		}
	}

	
	ret = FALSE;
	break;
 }

 /* last entry */
 if (state > 9 && entry.type != -1) 
	ImportAddEntry(&entry);

 /* conclude with updating register */
 if (filtentries > 0) {
	selRow = row;
	RegRedrawFilter(filtentries);
	AmiUpdateFilt(filtStr);	
 }
 AmiUpdateCurr(currStr);

 fclose(infile);
 return (ret);
}

/**************************************************************
* ExportAscii()
*
*	Export the filter as an ascii file
***************************************************************/
BOOL ExportAscii(char *file)
{
char tempAmnt[AMNTSIZE+1];
char str[200];
BOOL ret = TRUE;
filterNode *filt = NULL;
FILE *outfile;

 if ( (outfile = fopen(file,"w")) == NULL)
	return (FALSE);

 /* export starting information */
 fprintf(outfile,"source   %s\n\n",currFile);
  
 while ( (filt = (filterNode *)DataGetNext((struct List *)&filtered,(struct Node *)filt)) != NULL) {

	/* export entry type */
	switch (filt->entry->type) {
		case CHECKTYPE:
			sprintf(str,"%05d",filt->entry->check);
			break;
		case WITHDRAWALTYPE:
			sprintf(str,"Withdrawal");
			break;
		case DEPOSITTYPE:
			sprintf(str,"Deposit");
			break;
	}
	fprintf(outfile, "type     %s\n",str);
	
	/* export entry amount */
	DataBuildAmnt(TRUE,&filt->entry->amount,tempAmnt);
	fprintf(outfile, "amount   % 9s\n",tempAmnt);
	
	/* export date */
	DataBuildDate(&filt->entry->date,str);
	fprintf(outfile, "date     %s\n",str);

	/* export name */
	fprintf(outfile, "name     %s\n",filt->entry->name);

	/* export address */
	fprintf(outfile, "addr1\naddr2\naddr3\n");

	/* export memo */
	fprintf(outfile, "memo     %s\n",filt->entry->memo);

	/* export state */
	str[3]=0;
	if (filt->entry->flags & CLEARED)
		str[0]='Y';
	else	str[0]='N';

	if (filt->entry->flags & TAXDEDUCT)
		str[1]='Y';
	else	str[1]='N';
	
	if (filt->entry->flags & VOIDED)
		str[2]='Y';
	else	str[2]='N';

	fprintf(outfile, "state    %s\n",str);

	/* export category */
	fprintf(outfile, "category 0.00 %s\n",filt->entry->category);

	/* cute newline */
	fprintf(outfile,"\n");
 }


 fclose(outfile);
 return (ret);
}

/***************************************************************
* ImportAddEntry()
*
*	Import adding a complete entry into database 
****************************************************************/
void ImportAddEntry(entryNode *entry)
{
 filterNode *filt;
 entryNode *pos;

 /* insert into database */
 if (row == -1)
 	DataAddEntry(entry,&entries,&filt);
 else {
	DataInsertEntry(selFilt,selEntry,entry,&entries,&filt,&pos);
	if (pos != NULL) selEntry = pos;
	if (filt != NULL) selFilt = filt;
 }

 amiChangedItems = TRUE;

 /* update current balance */
 if (!(entry->flags & VOIDED)) {
	DataUpdateBal(entry->type,&entry->amount, &amntState.currAmnt, currStr);
	/*AmiUpdateCurr(currStr);*/
 }

 /* update the filter */
 if (filt != NULL) {
	filtentries++;

#if 0
	if (row == -1) {
		RegAddEntry(filt);
		AmiDisableSel(TRUE);
	}
	else {
		RegInsertEntry(row,filt);
	}
#endif
	/* update filter balance */
	if (!(entry->flags & VOIDED)) {
		DataUpdateBal(entry->type, &entry->amount, &filtAmnt, filtStr);
	/*	AmiUpdateFilt(filtStr);	*/
	}
 }

}
