#include "Includes.h"
#include "Defines.h"
#include "Protos.h"
#include "Version.h"
#include "Vars.h"

#include <link/io.h>

#pragma msg 217 ignore

/// __ACCOUNTING
__ACCOUNTING(int argc, char **argv)
{
   char buffer[128];

   DoAScript("PRE_ACCOUNTING.DMB",NULLFH);

   if(argc<1 || Stricmp(argv[0],"CLEAR"))
   {
      CP_CommandLine(4,"ACCOUNTING: CLEAR argument missing");
      return(0);
   }

   if(argc>1)
   {
      if(argc!=3)
      {
         CP_CommandLine(4,"ACCOUNTING: No address specified after ADDRESS keyword");
         return(0);
      }

      CP_CommandLine(4,"ACCOUNTING: Clearing call accounting for [%s]",argv[2]);
      Spawn(NULL, NULLFH, "FIDO:Trap/ClearAcct %s",argv[2]);
      return(0);
   }

   CP_CommandLine(4,"ACCOUNTING: Clearing call accounting for all addresses",argv[2]);
   Spawn(NULL, NULLFH, buffer,"FIDO:Trap/ClearAcct ALL");
   return(0);
}  
//-

/// __NODELIST
int __NODELIST(int argc, char **argv)
{
   char *how;

   DoAScript("PRE_NODELIST.DMB",NULLFH);

   if(argc<1)
   {
      CP_CommandLine(4,"NODELIST: No argument specifying method given");
      return 0;
   }

   how=argv[0];
   CP_CommandLine(4,"NODELIST: Processing method [%s]",how);

   if(0==Stricmp(how,"DIFF"))
   {
      CP_CommandLine(4,"NODELIST: DIFF - executing batch file");
      DoAScript("NLDiff.DMB",NULLFH);
      return 1;
   }

   if(0==Stricmp(how,"NEW"))
   {
      CP_CommandLine(4,"NODELIST: NEW - executing batch file");
      DoAScript("NLNew.DMB",NULLFH);
      return 1;
   }

   if(0==Stricmp(how,"RECOMPILE"))
   {
      CP_CommandLine(4,"NODELIST: RECOMPILE - executing batch file");
      DoAScript("NLRecompile.DMB",NULLFH);
      return 1;
   }

   DoAScript("POST_NODELIST.DMB",NULLFH);

   CP_CommandLine(4,"Unknown method argument [%s]",how);
   return 0;

}
//-

/// __CALL
int __CALL(int argc, char **argv)
{
   char address[50];
   char zone[50];
   char flavors[10];

   int c;

   int day,hour,minute,second;

   if(!IsTrapdoorThere(_BBSPORT)) return 0;

   if(!IsTrapdoorIdle(_TDPORT))   return 0;

   *address=NULL;
   *zone=NULL;
   *flavors=NULL;

   if(argc)
   {
      if(!Stricmp(argv[0],"ADDRESS") && argc>1)
      {
         strcpy(address,argv[1]);
         CP_CommandLine(4,"CALL: Specific address [%s]",address);
         CallIt(address);
         return(1);
      }

      if(!Stricmp(argv[0],"ZONE") && argc>1)
      {
         strcpy(zone,argv[1]);
         CP_CommandLine(4,"CALL: Limited to zone [%s]",zone);
      }
   }
   else
   {
      CP_CommandLine(4,"CALL: No modifiers, assuming any zone");
   }

   MyClock(&day,&hour,&minute,&second);

   c=_CALLTYPES[hour];
   c=Zone2Adjust(c,atoi(zone),hour,minute);

   switch(c)
   {
      case 'D':
      strcpy(flavors,"DNC");
      break;

      case 'Z':
      strcpy(flavors,"D");
      break;

      case 'N':
      strcpy(flavors,"NRC");
      break;

      case 'R':
      strcpy(flavors,"R");
      break;

      case 'C':
      strcpy(flavors,"C");
      break;
   }

   return(MasterCallRoutine(flavors,zone));
}
//-

/// __DELAYCALL
int __DELAYCALL(int argc, char **argv)
{
   int i=0;

   char address[50];
   char zone[50];
   char flavors[10];
   
   int delay=1000;
   int c;
   int day,hour,minute,second;

   *address=NULL;
   *zone=NULL;
   *flavors=NULL;

   if(argc)
   {
      while(i<argc)
      {
         if(0==Stricmp(argv[i],"SECONDS") && ((i+1)<argc))
         {
            i++;
            delay=min((  max((atoi(argv[i])*50),100)),1500);
            CP_CommandLine(4,"DELAYCALL: Delay set to [%d] seconds",delay/50);
            i++;
            continue;
         }
         else
         {
            if(0==Stricmp(argv[i],"ZONE") && ((i+1)<argc))
            {
               i++;
               strcpy(zone,argv[i]);
               CP_CommandLine(4,"DELAYCALL: Limited to zone [%s]",zone);
               i++;
               continue;
            }
            else
               i++;
         }
      }
   }
   else
   {
      CP_CommandLine(4,"CALL: No modifiers, assuming any zone, 8 second delay");
   }

   MyClock(&day,&hour,&minute,&second);

   c=_CALLTYPES[hour];
   c=Zone2Adjust(c,atoi(zone),hour,minute);

   switch(c)
   {
      case 'D':
      strcpy(flavors,"DNC");
      break;

      case 'Z':
      strcpy(flavors,"D");
      break;

      case 'N':
      strcpy(flavors,"NRC");
      break;

      case 'R':
      strcpy(flavors,"R");
      break;

      case 'C':
      strcpy(flavors,"C");
      break;
   }

   Delay(delay);

   return(MasterCallRoutine(flavors,zone));
}
//-

/// __CRASH
int __CRASH(int argc, char **argv)
{
   char zone[50];

   if(!IsTrapdoorThere(_BBSPORT)) return 0;
   if(!IsTrapdoorIdle(_TDPORT)) return 0;

   *zone=NULL;

   if(argc)
   {
      if(0==Stricmp(argv[0],"ZONE") && argc>1)
      strcpy(zone,argv[1]);
      CP_CommandLine(4,"CRASH: Limited to zone [%s]",zone);
   }
   else
   {
      CP_CommandLine(4,"CRASH: No modifiers, assuming any zone");
   }

   return(MasterCallRoutine("C",zone));

}
//-

/// __DIRECT
int __DIRECT(int argc, char **argv)
{
   char zone[50];

   if(!IsTrapdoorThere(_BBSPORT)) return 0;
   if(!IsTrapdoorIdle(_TDPORT)) return 0;

   *zone=NULL;

   if(argc)
   {
      if(0==Stricmp(argv[0],"ZONE") && argc>1)
      strcpy(zone,argv[1]);
      CP_CommandLine(4,"DIRECT: Limited to zone [%s]",zone);
   }
   else
   {
      CP_CommandLine(4,"DIRECT: No modifiers, assuming any zone");
   }

   return(MasterCallRoutine("DNC",zone));
}
//-

/// __DIRECTONLY
int __DIRECTONLY(int argc, char **argv)
{
   char zone[50];

   if(!IsTrapdoorThere(_BBSPORT)) return 0;
   if(!IsTrapdoorIdle(_TDPORT)) return 0;

   *zone=NULL;

   if(argc)
   {
      if(0==Stricmp(argv[0],"ZONE") && argc>1)
      strcpy(zone,argv[1]);
      CP_CommandLine(4,"DIRECTONLY: Limited to zone [%s]",zone);
   }
   else
   {
      CP_CommandLine(4,"DIRECTONLY: No modifiers, assuming any zone");
   }

   return(MasterCallRoutine("D",zone));
}
//-

/// __NORMAL
int __NORMAL(int argc, char **argv)
{
   char zone[50];

   if(!IsTrapdoorThere(_BBSPORT)) return 0;
   if(!IsTrapdoorIdle(_TDPORT)) return 0;

   *zone=NULL;

   if(argc)
   {
      if(0==Stricmp(argv[0],"ZONE") && argc>1)
      strcpy(zone,argv[1]);
      CP_CommandLine(4,"NORMAL: Limited to zone [%s]",zone);
   }
   else
   {
      CP_CommandLine(4,"NORMAL: No modifiers, assuming any zone");
   }

   return(MasterCallRoutine("NRC",zone));
}
//-

/// __REQUEST
int __REQUEST(int argc, char **argv)
{
   char zone[50];

   if(!IsTrapdoorThere(_BBSPORT)) return 0;
   if(!IsTrapdoorIdle(_TDPORT)) return 0;

   *zone=NULL;

   if(argc)
   {
      if(0==Stricmp(argv[0],"ZONE") && argc>1)
      strcpy(zone,argv[1]);
      CP_CommandLine(4,"REQUEST: Limited to zone [%s]",zone);
   }
   else
   {
      CP_CommandLine(4,"REQUEST: No modifiers, assuming any zone");
   }

   return(MasterCallRoutine("R",zone));
}
//-

/// Zone2Adjust
int Zone2Adjust(int c,int zone,int hour,int minute)
{
   int lasthour;
   int lc;

   lasthour=hour-1;
   if(lasthour<0) lasthour=23;

   if(_MyZone!=2) return c;

   if(zone!=2) return c;

   lc=_CALLTYPES[lasthour];

   if(c=='D' || c=='Z')
   {
      if(minute>29) return c;
      if(minute<30) return lc;
   }
   if(lc=='D' || lc=='Z')
   {
      if(minute>29) return c;
      if(minute<30) return lc;
   }
   return c;
}
//-

/// MasterCallRoutine
#define MAXDEST 100

int MasterCallRoutine(char *flavors,char *limzone)
{
   int limitzone=0;

   char ext[35];
   struct FileInfoBlock *FIB;
   BPTR fh;

   int i,j,totalfiles;
   
   char filearray[MAXDEST][32];
   char *fa[MAXDEST];
   int c, counter;

   char tmpstring[40];

   char cnet[10],cnode[10];
   int zone,net,node,point;

   BOOL typeC=FALSE;
   BOOL typeN=FALSE;
   BOOL typeD=FALSE;
   BOOL typeR=FALSE;

   if(!IsTrapdoorThere(_BBSPORT)) return 0;
   if(!IsTrapdoorIdle(_TDPORT)) return 0;

/*
 * 
 * Something new - hold off calling if the bundler is doing its thing
 * 
 */

   if(i_am_bundling && _NOCALLBUNDLE) return 0;
   if(i_am_processing && _NOCALLPROCESS) return 0;



   FIB=(void *)AllocMem(sizeof(struct FileInfoBlock),MEMF_PUBLIC);
   if(!FIB)
   {
      CP_CommandLine(4,"Couldn't allocate FIB for dialing");
      return 0;
   }


   limitzone=atoi(limzone);
   if(limitzone==0) limitzone=_AUTOCALLZONE;

   for(i=0;flavors[i]!=NULL;i++)
   {
      c=flavors[i];
      if(c=='C') typeC=TRUE;
      if(c=='R') typeR=TRUE;
      if(c=='D') typeD=TRUE;
      if(c=='N') typeN=TRUE;
   }

   fh=Lock("OUTBOUND:",ACCESS_READ);
   
   totalfiles=0;

   if(fh)
   {
      i=0;
      zone=1;  /* used to pass string "destzone" for conversion here */
      point=0;
   
      Examine(fh,FIB);
      while(1)
      {
         if(ExNext(fh,FIB))
         {
            if(FIB->fib_DirEntryType)
            {
            
               strcpy(tmpstring,FIB->fib_FileName);
               Upper(tmpstring);

               /*printf("looking at %s => ",tmpstring);*/

               /* we need to exclude certain extensions here */
               /* copy only the extension to a new string */

               for(counter=(strlen(tmpstring)-1) ; counter>0 ; counter--)
               {
                  c=tmpstring[counter];
                  if(c=='.') break;
               }
               /* counter should equal . or first char */
               if(counter) counter++; /* get rid of . */
               strcpy(ext,tmpstring+counter);

               /*printf("extension=%s\n",ext);*/

                  if((XMatch(ext,"DLO") || XMatch(ext,"DUT")) && typeD)
               {
                  strcpy(filearray[i],tmpstring);
                  i++;
               }
                  if((XMatch(ext,"FLO") || XMatch(ext,"OUT")) && typeN)
               {
                  strcpy(filearray[i],tmpstring);
                  i++;
               }
                  if((XMatch(ext,"CLO") || XMatch(ext,"CUT"))&& typeC)
               {
                  strcpy(filearray[i],tmpstring);
                  i++;
               }
                  if(XMatch(ext,"REQ") && typeR)
               {
                  strcpy(filearray[i],tmpstring);
                  i++;
               }
            }
            if(i==MAXDEST) break;
         }
         else break; /* nothing else to ExNext() */
      }
   
      totalfiles=i;
      UnLock(fh);
   }
   
   if(totalfiles)
   {
      for(i=0;i<totalfiles;i++)
      {
   
         if(DLGMAILSTOP) 
            break;

         /* convert whatever format the filename is in to 4D */

         counter=0;
         for(j=0;filearray[i][j]!=NULL;j++)
               if(filearray[i][j]=='.') counter++;
         if(counter==1) /* 2d format needs conversion */
         {
            zone=_MyZone; /*atoi(destzone);*/
            point=0;
            for(j=0;j<4;j++)
            {
               cnet[j]=filearray[i][j];
               cnode[j]=filearray[i][j+4];
            }
            cnet[4]=NULL;
            cnode[4]=NULL;
      
            stch_i(cnet,&net);   
            stch_i(cnode,&node);
   
            ASPrintf(NULL,filearray[i],"%d:%d/%d.%d",zone,net,node,point);
         }
         else
         {
            /* parse 4d address */
            for(j=0;filearray[i][j]!=NULL;j++)
            {
               if(filearray[i][j]=='.')
               {
                  filearray[i][j]=':';
                  break;
               }
            }
            
            for(j=0;filearray[i][j]!=NULL;j++)
            {
               if(filearray[i][j]=='.')
               {
                  filearray[i][j]='/';
                  break;
               }
            }
            
            for(j=0;filearray[i][j]!=NULL;j++)
            {
               if(filearray[i][j]=='.')
               {
                  filearray[i][j]='-';
                  break;
               }
            }
            
            for(j=0;filearray[i][j]!=NULL;j++)
            {
               if(filearray[i][j]=='.')
               {
                  filearray[i][j]=NULL;
                  break;
               }
            }
            
            for(j=0;filearray[i][j]!=NULL;j++)
            {
               if(filearray[i][j]=='-')
               {
                  filearray[i][j]='.';
                  break;
               }
            }
         }
         fa[i]=filearray[i];
      }
   
      tqsort(fa,totalfiles);

      strcpy(tmpstring,fa[0]);   /* get rid of dupes */
      for(i=1;i<totalfiles;i++)
      {
         if(0==Stricmp(tmpstring,fa[i]))
            strcpy(fa[i],"");
         else
            strcpy(tmpstring,fa[i]);
      }

      if(limitzone)
      {
         for(i=0;i<totalfiles;i++)
         {
            /*printf("LIMIT: zone %d, this zone is %d\n",limitzone,atoi(fa[i]));*/
            if(  atoi(fa[i]) !=  limitzone  )
            {
               /*printf("dumping above\n");*/
               strcpy(fa[i],"");
            }
         }
      }

      for(i=0;i<totalfiles;i++)
      {
         if(DLGMAILSTOP)
            break;
         
         if(strlen(fa[i]))
         {
            CallIt(fa[i]);
         }
      }
   }

   FreeMem(FIB,sizeof(struct FileInfoBlock));
   return(0);
}
//-

/// CallIt
int CallIt(char *add)
{
   char address[100];
   int rc;
   char arexxstring[110];
   char tmp[100];
   int zone=0,net=0,node=0,point=0;
   
   NumStrsfn(add,&zone,&net,&node,&point);
   if(zone==0) zone=_MyZone;
   ASPrintf(NULL,address,"%d:%d/%d.%d",zone,net,node,point);

   CP_CommandLine(4,"** Dial ** [%s] => [...]",address);

   ASPrintf(NULL,tmp,"CALL %s",address);

   rc=SendRexx(_TDPORT,tmp,arexxstring);
   rc=SendRexx2(_TDPORT,"STATUS D",arexxstring);

   if(*arexxstring)
      CP_CommandLine(4,"** Dial ** [%s] => [%s]",address,arexxstring);
   else
      CP_CommandLine(4,"** Dial ** [%s] => [No result string]",address);

   Delay(150);

   return(rc);
}
//-

/// __NO_PEND_TRAPDOOR
int __NO_PEND_TRAPDOOR(int argc, char **argv)
{
   char buf[100];

   if(argc)
   {
      if(0==Strnicmp(argv[0],"RECONFIG",8))
      {
         CP_CommandLine(4,"Rereading TrapDoor config file");
         ASPrintf(NULL,buf,"CONFIG %s",_TDCFGFILE);
         SendRexx2(_TDPORT,buf,NULL);
         CP_CommandLine(4,"TrapDoor config file reread");
      }

      if(0==Strnicmp(argv[0],"ANSWER",6))
      {
         CP_CommandLine(4,"Telling TrapDoor to answer on RINGS 1");
         SendRexx2(_TDPORT,"RINGS 1",NULL);
         CP_CommandLine(4,"TrapDoor will now answer incoming calls");
      }

      if(0==Strnicmp(argv[0],"NOANSWER",6))
      {
         CP_CommandLine(4,"Telling TrapDoor to answer on RINGS 9999");
         SendRexx2(_TDPORT,"RINGS 9999",NULL);
         CP_CommandLine(4,"TrapDoor will not answer incoming calls");
      }

      if(0==Strnicmp(argv[0],"ON",2))
      {
         __TD(1,0);
         Delay(50);
      }

      if(0==Strnicmp(argv[0],"OFF",3))
      {
         __TD(0,0);
         Delay(50);
      }
   }
   return 0;
}
//-

