/* **** Includes *********************************************************** */

#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/alib_protos.h>

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>

#include <HBBS/ANSI_Codes.h>
#include <HBBS/Defines.h>
#include <HBBS/Access.h>
#include <HBBS/types.h>
#include <HBBS/structures.h>

#include <HBBS/Hbbscommon_protos.h>
#ifdef __SASC
#include <HBBS/hbbscommon_pragmas_sas.h>
#else
#include <HBBS/hbbscommon_pragmas_stc.h>
#endif

#include <HBBS/Hbbsnode_protos.h>
#ifdef __SASC
#include <HBBS/Hbbsnode_pragmas_sas.h>
#else
#include <HBBS/Hbbsnode_pragmas_stc.h>
#endif

#include <HBBS/release.h>
char *versionstr="$VER: AddTime "RELEASE_STR;

/* **** Variables ********************************************************** */


struct Library *HBBSCommonBase  = NULL;
struct Library *HBBSNodeBase    = NULL;

struct BBSGlobalData *BBSGlobal = NULL;
struct NodeData *N_ND           = NULL;
int    N_NodeNum                = -1;
char   outstr[1024];

long __stack=16*1024; // increse this in 4k incrments if you suffer from
                      // random/suprious crashings after or during the running
                      // of your door.

/* **** Functions ********************************************************** */


#ifdef __SASC
int CXBRK(void) { return(0); }
int _CXBRK(void) { return(0); }
void chkabort(void) {}
#endif

BOOL UserAround=TRUE;

static VOID cleanup(ULONG num)
{
  if (HBBSNodeBase)
  {
    HBBS_CleanUpDoor();
    CloseLibrary (HBBSNodeBase);
  }

  if (HBBSCommonBase)
  {
    HBBS_CleanUpCommon();
    CloseLibrary (HBBSCommonBase);
  }

  if (num) printf("Door Error = %d\n",num);

  exit(0);
}

static VOID init(char *name)
{
  if(!(HBBSCommonBase = OpenLibrary("HBBSCommon.library",0)))
  {
    cleanup(1);
  }

  if (!(HBBS_InitCommon()))
  {
    cleanup(2);
  }

  if(!(HBBSNodeBase = OpenLibrary("HBBSNode.library",0)))
  {
    cleanup(3);
  }

  if (!(HBBS_InitDoor(N_NodeNum,name)))
  {
    cleanup(4);
  }
  SetProgramName(name);
}

void AwardTime(V_BIGNUM ConfNum,LONG Time,char *FileName)
{

  // *C* update for conference accounting..

  N_ND->User->CallData->TimeUsed-=Time;
  N_ND->User->NormalData->TimeUsed-=Time;

  if (N_ND->User->CallData->TimeUsed<0) N_ND->User->CallData->TimeUsed=0;
  if (N_ND->User->NormalData->TimeUsed<0) N_ND->User->NormalData->TimeUsed=0;

}

void DoorMain(int argc,char *argv[])
{
  struct CfgFileData *AutoAwardCFG=NULL;
  struct List *AwardFile=NULL;
  struct List *AwardOpts=NULL;
  LONG AwardSize=0,p,Matched=0;
  V_BOOL StopOnFirstMatch=TRUE;
  BOOL ExaminedOK=FALSE,FoundMatch,Done=FALSE;
  ULONG AwardFiles=0,BaudRate=0;
  V_BIGNUM ConfNum;
  struct Node *node,*node2;
  char matchstr[256];
  BPTR FL;
  V_STRING AwardMsg=NULL;
  LONG Mins;
  struct FileInfoBlock FB;

  if (UserAround) DOOR_WriteText(ANSI_RESET);

  if (sscanf(N_ND->ConnectBaud,"%ld",&BaudRate) && BaudRate>0)
  {
    BaudRate=BaudRate/10; // to get CPS.. from BPS

    ConfNum=atoi(argv[2]);

    if ((ConfNum<1) || (ConfNum>BBSGlobal->Conferences))
    {
      if (UserAround) DOOR_SysopText("Invalid Conference!\r\n");
    }
    else
    {
      // get details about the file that was uploaded..

      strcpy(outstr,N_ND->NodeSettings.NodePlayPen);
      strcat(outstr,argv[3]);
      if (FL=Lock(outstr,ACCESS_READ))
      {
        if (Examine(FL,&FB))
        {
          ExaminedOK=TRUE;
        }
        UnLock(FL);
      }
      if (!ExaminedOK)
      {
        sprintf(outstr,"Error Awarding Time\n"
                       "User: %s\n"
                       "File: %s\n"
                       "Reason: Could Not find File!",N_ND->User->CallData->Handle,argv[3]);
        HBBS_LogError(BBSGlobal->ErrorLogFile,ERR_GENERAL,outstr,TYPE_WARNING);
        if (UserAround) DOOR_SysopText("Could Not Find File!\r\n");
      }
      else
      {
        // get the filename of the config file (same dir as executable..)
        strcpy(outstr,argv[0]);
        if ((p=iposition(".HBBS",outstr))==(strlen(outstr)-5))
        {
          outstr[p]=0; //terminate string at the "."
        }
        strcat(outstr,".CFG");


        if (AutoAwardCFG=HBBS_LoadConfig(outstr,LCFG_NONE))
        {
          HBBS_GetSetting(AutoAwardCFG,(void *)&StopOnFirstMatch,VTYPE_BOOL,"StopOnFirstMatch",OPT_SINGLE);
          if (AwardFiles=HBBS_GetSetting(AutoAwardCFG,(void *)&AwardFile,VTYPE_STRINGLIST,"AwardFile",OPT_MULTI))
          {
            if (AwardFiles==HBBS_GetSetting(AutoAwardCFG,(void *)&AwardOpts,VTYPE_STRINGLIST,"AwardOpts",OPT_MULTI))
            {
              for (node = AwardFile->lh_Head , node2 = AwardOpts->lh_Head ; node->ln_Succ && node2->ln_Succ && !Done ; node =node->ln_Succ,node2 =node2->ln_Succ)
              {
                FoundMatch=FALSE;
                ParsePatternNoCase(node->ln_Name,matchstr,255);
                if (MatchPatternNoCase(matchstr,argv[3]))
                {
                  if (node2->ln_Name[0]) // a blank string ?
                  {
                    AwardSize=0;
                    sscanf(&node2->ln_Name[1],"%ld",&AwardSize);
                    if (AwardSize>0)
                    {
                      switch(node2->ln_Name[0])
                      {
                        case '+':
                          FoundMatch=TRUE;
                          AwardSize=FB.fib_Size+AwardSize;
                          break;
                        case '-':
                          FoundMatch=TRUE;
                          AwardSize=FB.fib_Size-AwardSize;
                          break;
                        case '*':
                          FoundMatch=TRUE;
                          AwardSize=FB.fib_Size*AwardSize;
                          break;
                        case '/':
                          FoundMatch=TRUE;
                          AwardSize=FB.fib_Size/AwardSize;
                          break;
                      }
                      if (FoundMatch)
                      {
                        Matched++;
                        Mins=(AwardSize/BaudRate)/60;

                        if (UserAround)
                        {

                          sprintf(outstr,"AwardMsg_%d",GetNodeNum(AwardFile,node)+1);
                          AwardMsg=NULL;
                          if (HBBS_GetSetting(AutoAwardCFG,(void *)&AwardMsg,VTYPE_STRING,outstr,OPT_SINGLE))
                          {
                            DOOR_WriteText(AwardMsg);
                            DOOR_WriteText("\r\n");

                            FreeStr(AwardMsg);
                          }

                          sprintf(outstr,ANSI_RESET ANSI_FG_YELLOW "Awarding %ld%s=%ld minute%s for %s\r\n" ANSI_RESET,(FB.fib_Size/BaudRate)/60,node2->ln_Name,Mins,Mins == 1 ? "" : "s",argv[3]);
                          DOOR_WriteText(outstr);
                        }

                        AwardTime(ConfNum,Mins,argv[3]);
                      }
                    }
                  }
                }
                if (StopOnFirstMatch && FoundMatch) Done=TRUE;
              }
              if (Matched==0)
              {
                Mins=(FB.fib_Size/BaudRate) / 60;

                if (UserAround)
                {
                  sprintf(outstr,ANSI_RESET ANSI_FG_GREEN "Awarding %ld minute%s for %s\r\n" ANSI_RESET,Mins,Mins == 1 ? "" : "s",argv[3]);
                  DOOR_WriteText(outstr);
                }
                AwardTime(ConfNum,Mins,argv[3]);
              }
              FreeStrList(AwardOpts);
            }
            else if (UserAround) DOOR_WriteText("Config File Mismatch\r\n");
            FreeStrList(AwardFile);
          }
          HBBS_FlushConfig(AutoAwardCFG);
        }
        else
        {
          AwardTime(ConfNum,FB.fib_Size/BaudRate,argv[2]);
        }
      }
    }
  }
}

int main(int argc,char *argv[])
{
  if (sscanf(argv[1],"%d",&N_NodeNum)==0)
  {
    printf("Invalid/No Paramaters for door!\n");
    exit (20);
  }

  if (stricmp("NOUSER",argv[argc-1])==0) UserAround=FALSE;


  init("AddTime");

  if (BBSGlobal=HBBS_GimmeBBS())
  {
    if (N_ND=HBBS_NodeDataPtr(N_NodeNum)) // this should not fail in normal circumstances..
    {
      if (N_ND->OnlineStatus!=OS_ONLINE) UserAround=FALSE;
      DoorMain(argc,argv);
    }
  }
  cleanup(0);
}
