#include <exec/exec.h>
#include <dos/dos.h>
#include <stdio.h>
#include <stdlib.h>
#include "dh0:code/aelib/ae_pragmas.h"
#include "dh1:source/doors/romconf/doorheader.h"
extern struct Library *AEBase;
char Name[200];
char LastDate[200];
#define NAME 1
#define LASTON 2
#define FIRSTON 3
#define ACCOUNTDATE 4
#define MONEYTHISPERIOD 5
#define MONEYTOTAL 6
#define BTOTAL 7
#define BPTOTAL 8
#define BTOTALUSED 9
#define BPTOTALUSED 10
#define COSTPERMEG 11
#define DAYSTOTAL 12
#define DAYSPTOTAL 13
#define ACTIVE 14
#define sr StripReturn
#define g(x,y) { sprintf(temp,"[%d;%dH",y,x); sm(temp,0); }
#define CLEARPROMPT sm("                                                                      ",0)

struct User
{
  char name[31];
  char comment[5][80];
  long datelaston;
  long datefirston;
  long accountdate;
  long money_this_period;
  long money_total;
  long mbytes_total_purchase;
  long mbytes_period_purchase;
  long mbytes_total_used;
  long mbytes_this_period;
  long costper_mbyte;
  long days_remaining;
  long days_total_purchased;
  long days_period_purchased;
  long originalbytes;
  BOOL active;
} U;
#define CLEAR ""
#define ALL 0
char temp[10];
void LastCommand(void);
void end(void);
void ChangeInfo(int opt,struct User *u);
void DisplaySpec(int opt,struct User *u);
void Display(struct Userr *u);
void InitUser(struct User *u);
void LoadUser(struct User *u);
void SaveUser(struct User *u);
void LoadSpec(struct User *u);
void LookFor(struct User *u,int opt);
int notallowed(char *s);
#define USER_NAME 1
#define DATES 2
#define USER_PAID 3
#define USER_MEG_PAID 4
#define USER_MEG_USED 5
#define USER_DAYS_USED 6
#define USER_DAYS_PAID 7
#define USER_MEG_COST 8
#define USER_STATUS 9
#define STATBAR 10
#define CHG_NAME 1
#define CHG_PAID_T 2
#define CHG_PAID_H 3
#define CHG_MEGPUR_T 4
#define CHG_MEGPUR_H 5
#define CHG_MEGUSE_T 6
#define CHG_MEGUSE_H 7
#define CHG_DAYPUR_T 8
#define CHG_DAYPUR_H 9
#define OPT_NAME 'a'
#define OPT_PAID_T 'b'
#define OPT_COSTMEG 'g'
#define OPT_PAID_H 'h'
#define OPT_MEGPUR_T 'c'
#define OPT_MEGPUR_H 'i'
#define OPT_MEGUSE_T 'd'
#define OPT_MEGUSE_H 'j'
#define OPT_DAYPUR_T 'e'
#define OPT_DAYPUR_H 'k'

#define HIST sm("[44m[36mCHG-HIST[0m[33m:[32m")
#define TERM sm("[44m[36mCHG-TERM[0m[33m:[32m")

#define Show(x) DisplaySpec(x,(struct User *)&U)
#define sm sendmessage
#define pm prompt
#define gu getuserstring
#define pu putuserstring
long account=0L;
char config[200];
char yourname[100];
BOOL ViewOnly=TRUE;
main(int argc,char *argv[])
{
  if(argc!=2)
  {
    printf("ACCOUNTANT version 1.0, written by Joseph Hodge\n");
    printf("This is a (XIM) for /X version 2.1+\n");
    printf("\n");
    printf("\n");
    exit(0);
  }
  
  Register(argv[1][0]-'0');
  strcpy(config,argv[0]); StripReturn(config);
  InitUser(&U);
  strcpy(yourname,U.name);
  LoadUser(&U);
  ViewOnly=notallowed(yourname);
  sm(CLEAR,0);
  Display(&U);
  if(!ViewOnly)
  {
  do
  {
    hotkey("",temp);
    switch(temp[0])
    {
      case 'A': LookFor((struct User *)&U,1); Display(&U);break;
      case 'l': if(!U.active){
                U.accountdate=time(NULL); U.active=TRUE;}
               else {U.accountdate=0L; U.active=FALSE; } Show(USER_STATUS); Show(DATES); Show(STATBAR);break;
      case 'R': 
                U.money_total += U.money_this_period; U.money_this_period=0L;
                U.mbytes_total_purchase +=U.mbytes_period_purchase; U.mbytes_period_purchase=0L;
                U.mbytes_total_used+=U.mbytes_this_period;U.mbytes_this_period=0L;
                U.days_remaining=0L;
                U.days_total_purchased+=U.days_period_purchased; U.days_period_purchased=0L;
                U.active=FALSE; U.accountdate=0L;
                Display((struct User *)&U); 
      case 'L': LookFor((struct User *)&U,0); 
                Display(&U); break;
      case 'N': account +=1L; LoadSpec((struct User *)&U); Display(&U);break;
      case 'P': account -=1L; LoadSpec((struct User *)&U); Display(&U);break;
      case 'S': SaveUser(&U); break;
      case 'Q': ShutDown(); end(); break;
      default: ChangeInfo(temp[0],(struct User *)&U); Display((struct User *)&U);break;
    }
   }while(1);
   }
   ShutDown(); end();
}
void LookFor(struct User *u,int opt)
{
   FILE *fi;
   struct User a;
   LONG accountnum=0L;
   LONG slot=-1L;
   char FName[200];
   char name[200];
   char name2[200];
   char temp[100];
  
   g(7,20);
   CLEARPROMPT; g(7,20);
   if(!opt)
   {
   pm("[44m[36mLOOKFOR[0m[33m:[32mEnter Name [36m>: [0m",name,31);
   }
   else
   pm("[44m[36mADD ACCOUNT[0m[33m:[32mEnter Name [36m>: [0m",name,31); strupr(name);
   if(name[0]=='\0') return;
   sprintf(FName,"%s.db",config); 
   fi=fopen(FName,"r+b");
   if(fi==NULL) return;
   while(fread((APTR)&a,sizeof(struct User),1,fi)!=NULL)
   {
      if(!u->active && slot==-1L)slot=accountnum;
      strcpy(name2,a.name); strupr(name2);
      if(!strcmp(name,name2)) { fseek(fi,(LONG)sizeof(struct User)*accountnum,0L);
                                fread((APTR)u,sizeof(struct User),1,fi);fclose(fi);
                                account=accountnum; return;
                              }
       accountnum +=1L;
   }
   fclose(fi);
   g(7,20); CLEARPROMPT;
   if(!opt)
   {
   g(7,20); sm("[33mAccount ",0); sm("[32m",0); sm(name,0); sm("[33m does not exist[0m\a",0);
   }
   else 
   { 
     g(7,20);
     InitUser((struct User *)u); strcpy(u->name,name);
     u->datelaston=0L; u->datefirston=0L;u->accountdate=time(NULL);
     if(slot>=0L)
     {
       fi=fopen(FName,"r+b"); fseek(fi,(LONG)sizeof(struct User)*slot,0L);
       fwrite((APTR)u,sizeof(struct User),1,fi); fclose(fi); account=slot;
     } 
     else
     {
     fi=fopen(FName,"ab");  fwrite((APTR)u,sizeof(struct User),1,fi);
     fclose(fi); account =-1L;}
     LoadSpec(u); 
   }
   
   //Delay(70L);
}
   
int notallowed(char *s)
{
   FILE *fi;
   char FName[200];
   char temp[200];
   sprintf(FName,"%s.cfg",config);
   fi=fopen(FName,"r");
   if(fi==NULL) return(1);
   strcpy(temp,s);strupr(temp);
   while(fgets(FName,80,fi)!=NULL)
   {
     strupr(FName); StripReturn(FName);
     if(!strcmp(FName,temp)) { fclose(fi); return(0); }
   }
   fclose(fi);
   return(1);
}
void LoadSpec(struct User *u)
{
   FILE *fi;
   char FName[200];
   struct FileInfoBlock *FBlock;
   BPTR FLock;
   long Fsize;
 sprintf(FName,"%s.db",config);
   FLock = Lock(FName,ACCESS_READ);
   FBlock=AllocMem((long)sizeof(struct FileInfoBlock),MEMF_CHIP);
	if( Examine(FLock,FBlock) )		Fsize = FBlock->fib_Size;
	UnLock(FLock);
	FreeMem(FBlock,sizeof(struct FileInfoBlock));
  
   if(account>(Fsize/((LONG)sizeof(struct User)))-1L) account=0L;
   if(account<0L) account=Fsize/((LONG)sizeof(struct User))-1L;
   fi=fopen(FName,"rb");
   if(fi==NULL) return;
   fseek(fi,account*((LONG)sizeof(struct User)),0L);
   fread((APTR)u,sizeof(struct User),1,fi);
   fclose(fi);
   if(u->datefirston==0L) u->datefirston=u->datelaston;
}
void LoadUser(struct User *u)
{
  FILE *fi;
  char FName[200];
  char temp[200];
  ULONG times;
  LONG openaccount=-1L;
  LONG bytes;
  LONG remainder;
  LONG tempnum;
  sprintf(FName,"%s.db",config);
  fi=fopen(FName,"r+b");
  if(fi==NULL) 
  {  fi=fopen(FName,"ab");
  fwrite((APTR)u,sizeof(struct User),1,fi);
  fclose(fi);return;}
  account=0L;
  gu(Name,DT_TIMELASTON);
  while(fread((APTR)u,sizeof(struct User),1,fi)!=NULL)
  {
    if(!u->active && openaccount==-1L) openaccount=account;
    if(!strcmp(u->name,yourname)) 
    { 
       if(u->active)
       {
         u->datelaston=(ULONG)atol(Name);
         if(u->datefirston==0L) u->datefirston=atol(Name);
         if(u->mbytes_period_purchase)
         {
           gu(temp,DT_BYTEDOWNLOAD);
           bytes=(atol(temp)-u->originalbytes)/1000L;
           remainder=(u->mbytes_period_purchase-u->mbytes_this_period)-bytes;
           if(remainder<0)
           {
             u->mbytes_this_period=u->mbytes_period_purchase;
             tempnum=atol(temp)-(bytes*1000L)-(remainder*1000L);
             sprintf(temp,"%ld",tempnum); pu(temp,DT_BYTEDOWNLOAD);
           }
           else
           {
             if(u->mbytes_this_period!=u->mbytes_period_purchase)
             {
               u->mbytes_this_period += (atol(temp)-u->originalbytes)/1000L;
               tempnum=atol(temp)-(bytes*1000L);
               sprintf(temp,"%ld",tempnum); pu(temp,DT_BYTEDOWNLOAD);
             }
           }
         }
         if(u->days_period_purchased)
         {
            times=time(NULL)-u->accountdate;
            u->days_remaining=u->days_period_purchased - (times/(60L*24L));
         }
      }
      fclose(fi); return;}
    account +=1L;
  }
  fclose(fi);
  InitUser(u); 
  if(openaccount >-1L)
  {
    fi=fopen(FName,"r+b");
    fseek(fi,(LONG)sizeof(struct User)*openaccount,0L);
    fwrite((APTR)u,sizeof(struct User),1,fi);
    fclose(fi);
    account=openaccount;
    return;
  }
  fi=fopen(FName,"ab");
  fwrite((APTR)u,sizeof(struct User),1,fi);
  fclose(fi);
}
void SaveUser(struct User *u)
{
  FILE *fi;
  char FName[200];
  sprintf(FName,"%s.db",config);
  fi=fopen(FName,"r+b");
  if(fi==NULL) return;
  fseek(fi,(ULONG)(sizeof(struct User))*(ULONG)account,0);
  fwrite((APTR)u,sizeof(struct User),1,fi);
  fclose(fi);
}
void LastCommand(void)
{
  if(!ViewOnly){sm("",1);sm("",1); sm("",1);}else SaveUser(&U);sm("",1);
}
void end(void)
{
  exit(0);
}
#define DISData(opt,x,y) { sprintf(temp,"[33m%c[32m>[36m%s[33m: [0m%s   ",ViewOnly ? ' ':opt,x,y); sm(temp,0); }
#define DISMoney(opt,x,y,z) { sprintf(temp,"[33m%c[32m>[36m%s[33m: [0m%s",ViewOnly ? ' ':opt,x,y); sm(temp,0); sprintf(temp,"%6ld   ",z); sm(temp,0); }
#define g(x,y) { sprintf(temp,"[%d;%dH",y,x); sm(temp,0); }
#define gu getuserstring
void Display(struct User *u)
{
   int i=1;
   char temp[200];
   char mytemp[200];

          g(1,1); sm("[44m                            [36m/X [33mACCOUNTANT [32mv1.0                ",0);
                  sm("           [0m ",1);
          g(1,2); sm("[33m-------------------------------------------------------------------------[0m",1);
           g(5,4); DISData('a',"Name         ","                               ");   
 
          g(5,4); DISData('a',"Name         ",u->name); 
        strcpy(mytemp,GetTheDate(u->accountdate));
          g(5,5);  DISData('*',"Account Date ",u->accountdate ? mytemp:"N/A    "); 
          g(5,6); 
          strcpy(mytemp,GetTheDate(u->datelaston));
          DISData('*',"Last  On     ", !u->datelaston ? "UNKNOWN":mytemp); 

           strcpy(mytemp,GetTheDate(u->datefirston));
          DISData('*',"First On     ",!u->datefirston ? "UNKNOWN":mytemp); 

          g(5,9); 
   if(!ViewOnly)
   {
   sm("     [47m[33m  ACCOUNT THIS TERM  [0m[36m           [47m   ACCOUNT HISTORY   [0m",1); 
   }
   else   sm("     [44m[33m  ACCOUNT THIS TERM  [0m[36m           [44m   ACCOUNT HISTORY   [0m",1); 

  
          g(5,11);  DISMoney('b',"Amount Paid      ","$ ",u->money_this_period);
                   DISMoney('h',"Amount Paid     ","$ ",u->money_total); 

          g(5,12); DISMoney('c',"Megs Purchased   ","  ",u->mbytes_period_purchase);
                   DISMoney('i',"Megs Purchased  ","  ",u->mbytes_total_purchase);
     
          g(5,13); DISMoney('d',"Megs Used        ","  ",u->mbytes_this_period);
                   DISMoney('j',"Megs Used       ","  ",u->mbytes_total_used);
          g(5,14); DISMoney('e',"Days Purchased   ","  ",u->days_period_purchased);
                   DISMoney('k',"Days Purchased  ","  ",u->days_total_purchased); 
          g(5,15); DISMoney('f',"Days Remaining   ","  ",u->days_remaining);
          g(5,17); DISMoney('g',"Cost Per Meg     ","$ ",u->costper_mbyte);
                   DISData('l',"Account         ", u->active ? "ACTIVE":"INACTIVE"); 
          g(1,19); sm("[33m-------------------------------------------------------------------------[0m",1);
 if(!ViewOnly)
 {
         g(5,20); sm("  [33mA[32m)[36mdd   [33mS[32m)[36mave   [33mL[32m)[36mookFor   [33mN[32m)[36mext",0);
                  sm("   [33mP[32m)[36mrior[0m   [33mR[32m)[36mecord   [33mQ[32m)[36muit[0m",1);
 
          
   g(1,21); sm("[33m-------------------------------------------------------------------------[0m",1);
   sm("",1);
 }
 else
 {          g(1,20);    sm("[44m   [36mWritten by ByteMaster[35m,  [33m/X [36mDevelopement Team [31m- [35mThe Silent Achievers   [0m",0);
 sm("",1);
 }
   if(!ViewOnly)
   {
     
          g(1,22);   sm("[44m   [36mWritten by ByteMaster[35m,  [33m/X [36mDevelopement Team [31m- [35mThe Silent Achievers   [0m",0);

        //  sm("[44m                                                                         [0m",0);
          g(70,20);
  }
}
void DisplaySpec(int opt,struct User *u)
{
   int i=1;
   char temp[200];
   char mytemp[200];
   switch(opt)
   {
    case USER_NAME:
           g(5,4); DISData('a',"Name         ","                               "); 
 
          g(5,4); DISData('a',"Name         ",u->name); 
          break;
    case DATES:
          strcpy(mytemp,GetTheDate(u->accountdate));
          g(5,5);  DISData('*',"Account Date ",u->accountdate ? mytemp:"N/A    "); 
          strcpy(mytemp,GetTheDate(u->datelaston));
          g(5,6);
          DISData('*',"Last  On     ", !u->datelaston ? "UNKNOWN":mytemp); 

          
                 strcpy(mytemp,GetTheDate(u->datefirston));
          DISData('*',"First On     ",!u->datefirston ? "UNKNOWN":mytemp); 

          break;
    case USER_PAID:    
          g(5,11);  DISMoney('b',"Amount Paid      ","$ ",u->money_this_period);
                    DISMoney('h',"Amount Paid     ","$ ",u->money_total); 
          break;
    case USER_MEG_PAID:
          g(5,12); DISMoney('c',"Megs Purchased   ","  ",u->mbytes_period_purchase);
                   DISMoney('i',"Megs Purchased  ","  ",u->mbytes_total_purchase);
         break;
    case USER_MEG_USED:
          g(5,13); DISMoney('d',"Megs Used        ","  ",u->mbytes_this_period);
                   DISMoney('j',"Megs Used       ","  ",u->mbytes_total_used);
         break;
    case USER_DAYS_PAID:
          g(5,14); DISMoney('e',"Days Purchased   ","  ",u->days_period_purchased);
                   DISMoney('k',"Days Purchased  ","  ",u->days_total_purchased); 
          break;
    case USER_DAYS_USED:
          g(5,15); DISMoney('f',"Days Remaining   ","  ",u->days_remaining);
          break;
    case USER_MEG_COST:
          g(5,17); DISMoney('g',"Cost Per Meg     ","$ ",u->costper_mbyte);
          break;
    case USER_STATUS:
         g(5,17); DISMoney('g',"Cost Per Meg     ","$ ",u->costper_mbyte);
                   DISData('l',"Account         ", u->active ? "ACTIVE":"INACTIVE"); 
         break;
    case STATBAR:
          g(1,19); sm("[33m-------------------------------------------------------------------------[0m",1);
          g(5,20); sm("  [33mA[32m)[36mdd   [33mS[32m)[36mave   [33mL[32m)[36mookFor   [33mN[32m)[36mext",0);
                sm("   [33mP[32m)[36mrior[0m   [33mR[32m)[36mecord   [33mQ[32m)[36muit[0m",1);
             g(1,21); sm("[33m-------------------------------------------------------------------------[0m",1);
          sm("",1);g(70,20);
    break;
  }
}
void ChangeInfo(int opt,struct User *u)
{
      char temp[200];
   char mytemp[200];
   
   g(7,20);
   CLEARPROMPT;
   g(7,20);
   switch(opt)
   {
     case OPT_NAME: 
           pm("[44m[36mCHG[0m[33m:[32mName         [33m>:[0m",temp,31);
           if(temp[0]!='\0') strcpy(u->name,temp);break;
    case OPT_PAID_T:
           pm("[44m[36mCHG-TERM[0m[33m:[32mAmount Paid      $ [33m>:[0m",temp,10);
           u->money_this_period=atol(temp); break;
     case OPT_PAID_H:
           pm("[44m[36mCHG-HIST[0m[33m:[32mAmount Paid      $ [33m>:[0m",temp,10);
           u->money_total=atol(temp); 
          break;
     case OPT_MEGPUR_T:
          TERM;pm("Megs Purchased     [33m>:[0m",temp,10);
               u->mbytes_period_purchase=atol(temp);break;
     case OPT_MEGPUR_H:
          HIST;pm("Megs Purchased     [33m>:[0m",temp,10);
               u->mbytes_total_purchase=atol(temp);break;
     case OPT_MEGUSE_T:
          TERM;pm("Megs Used          [33m>:[0m",temp,10);
               u->mbytes_this_period=atol(temp); break;
     case OPT_MEGUSE_H:
          HIST;pm("Megs Used          [33m>:[0m",temp,10);
               u->mbytes_total_used=atol(temp);break;
     case OPT_DAYPUR_T:
          TERM;pm("Days Purchased     [33m>:[0m",temp,10);
               u->days_period_purchased =atol(temp); break;
     case OPT_DAYPUR_H:
          HIST;pm("Days Purchased     [33m>:[0m",temp,10);
               u->days_total_purchased=atol(temp);
          break;
     case OPT_COSTMEG:
          pm("[32mCost Per Meg       [33m>:[0m",temp,10);
               u->costper_mbyte=atol(temp); break;
  }
          g(1,19); sm("[33m-------------------------------------------------------------------------[0m",1);
          g(5,20); sm("  [33mA[32m)[36mdd   [33mS[32m)[36mave   [33mL[32m)[36mookFor   [33mN[32m)[36mext",0);
                   sm("   [33mP[32m)[36mrior[0m   [33mR[32m)[36mecord   [33mQ[32m)[36muit[0m",1);
          g(1,21); sm("[33m-------------------------------------------------------------------------[0m",1);
          sm("",1);g(70,20);
}
void InitUser(struct User *u)
{
  gu(Name,DT_NAME);
  strcpy(u->name,Name);
  gu(Name,DT_TIMELASTON);
  u->datelaston=(ULONG)atol(Name);
 
  u->datefirston=u->datelaston;
  u->accountdate=0L;
  u->money_this_period=0L;
  u->money_total=0L;
  u->mbytes_total_purchase=0L;
  u->mbytes_period_purchase=0L;
  u->mbytes_total_used=0L;
  u->mbytes_this_period=0L;
  u->costper_mbyte=0L;
  u->days_total_purchased=0L;
  u->days_period_purchased=0L;
  u->originalbytes=0L;
  u->active=TRUE;
}