#include "DLGAreaFix.h"

#include <link/io.h>

int               FindDeadEnds(char *, char *);
int               ProcessDeadEnds(char *, char *);
void              DeadEndUseage(void);
void              RemoveArea(char *);

/// FindDeadEnds
FindDeadEnds(char *address, char *file)
{
   char  add[100];
   struct area      *ThisArea;
   struct nodenum   *nn;
   int   count = 0;
   BPTR  fh;
   char *r;

   char  o[MAX_STR];
   unsigned long  z, N, n, p;

   strcpy(add, address);
   r = strchr(add, '!');
   
   if (r)
      *r = 32;
   
   sscanf(add, "%s %lu:%lu/%lu.%lu", o, &z, &N, &n, &p);

   AFPrintf(NULL,sout,"Looking for deadends for [%s!%lu:%lu/%lu.%lu]\n", o, z, N, n, p);

   ThisArea = a->first_area;

   if (ThisArea)
   {
      fh = Open(file, MODE_NEWFILE);

      if (fh)
      {
         for (; ThisArea; ThisArea = get_next_area(ThisArea))
         {
            if (ThisArea->passthru)
            {
               if (!Stricmp(ThisArea->from_organization, o))
               {
                  nn = ThisArea->first_nodenum;

                  if (nn)
                  {
                     if (!nn->next_nodenum)
                     {
                        if (!Stricmp(nn->organization, o) &&
                             nn->zone == z &&
                             nn->net == N &&
                             nn->node == n &&
                             nn->point == p)
                        {
                           // deadend area found!

                           AFPrintf(NULL, fh, "-%s\n", ThisArea->name);
                           AFPrintf(NULL, sout, "Found dead area [%s]\n", ThisArea->name);
                           ASPrintf(NULL, logstring, ".  Found dead area [%s]", ThisArea->name);
                           Log(logstring);
                           count++;
                        }
                     }
                  }
               }
            }
         }

         AFPrintf(NULL,fh, "---\n");
         AFPrintf(NULL,fh, "%d dead areas found to disconnect\n", count);
         Close(fh);
      }
   }
   return(count);
}
//-

/// ProcessDeadEnds
ProcessDeadEnds(char *address, char *file)
{
   BOOL match = FALSE;

   BPTR fh = NULL;

   char  buf[1000];
   char  MyDomain[50];
   char *ToName;
   char *PW;
   char *MyAddr;
   char  FromName[200];
   char  domain[50];

   short zone,net,node,point;
   short MyZone,MyNet,MyNode,MyPoint;

   Log("-> Disconnecting from deadend areas ...");

   if(-1 == parse5dstring(address, MyDomain, &MyZone, &MyNet, &MyNode, &MyPoint))
   {
      Log("!  Supplied address is bogus!");
      return(0);
   }

   ASPrintf(NULL,logstring,".  Address to disconnect from is [%s]",address);
   Log(logstring);

/// Parse DLGMail.AFX and locate the info we need
   Log("-> Determining system to send AreaFix to...");

   fh = Open("Fido:DLGMail.AFX",MODE_OLDFILE);

   if(!fh) return(0);

   while(FGets(fh,buf,1000))
   {
      int c;
      char *t[20];

      StripSpaces(buf);

      if(buf[0] == ';') continue;

      if(Strnicmp(buf,"FEED",4)) continue;

      c = ArgParse(buf,t,19);

      if(c < 8)
      {
         Log("!  DLGMail.AFX not properly set up!");
         break;
      }

      if(-1 == parse5dstring(t[1], domain, &zone, &net, &node, &point))
      {
         Log("!  DLGMail.AFX FEED line error!");
         break;
      }

      if(!Stricmp(MyDomain,domain)  &&    (MyZone == zone)  &&
         (MyNet == net) && (MyNode == node)  && (MyPoint == point))
      {
         int i;

         match = TRUE;

         ToName = strdup(t[3]);
         PW = strdup(t[4]);
         MyAddr = strdup(t[6]);
         ASPrintf(NULL,FromName,"%s",t[7]);

         for(i = 8; i < c; i++)
         {
            strcat(FromName," ");
            strcat(FromName,t[i]);
         }

      }
   }

   if(fh) Close(fh);

   Log("<- Found entry in DLGMail.AFX.");

   if(!match)
   {
      ASPrintf(NULL,logstring,"<- No FEED entry found for [%s], can't disconnect",address);
      Log(logstring);
      return(0);
   }
//-

/// Send message
   Log("-> Sending message to upstream node");
   ASPrintf(NULL,logstring,"DLG:SendMsg -f \"%s\" -s %s -b %s -n -q -r \"NET %d:%d/%d.%d %s\"",
                            FromName,PW,file,MyZone,MyNet,MyNode,MyPoint,ToName);

   if(!Spawn(Input(),sout, logstring))
   {
      Log("<- Message sent OK");
   }
   else
   {
      Log("<- Error sending message!");
   }
//-

   Log("-> Deleting areas from DLGMail.ARE...");

   Copy("Fido:DLGMail.ARE","Fido:DLGMail.AREBAK");

   fh = Open(file,MODE_OLDFILE);

   if(!fh) return(0);

   while(FGets(fh,buf,1000))
   {
      int c;
      char *t[5];
      char T[100];

      StripSpaces(buf);

      if(buf[0] == ';') continue;

      if(!Strnicmp(buf,"---",3)) break;

      c = ArgParse(buf,t,4);

      if(c < 1) continue;

      strmid(t[0],T,2,strlen(t[0]));

      RemoveArea(T);
   }

   if(fh) Close(fh);

   Log("<- Done deleting area");

   Log(".  Reloading areas");

   Spawn(NULL,sout, "Fido:DMC RELOADARE");

   Log("<- Finished disconnecting.");
   return(0);
}
//-

/// DeadEndUseage
void DeadEndUseage(void)
{
   AFPrintf(NULL,sout,"Useage: DLGAreaFix DEADEND <3Daddress> <reportfilename | DISCONNECT>\n");
}
//-

/// DeadEnd
DeadEnd(int argc, char **argv)
{
   char  address[100];
   char  sysop[100];
   char  outfile[100];
   int   rc = 0;
   int   count;

   strcpy(address, argv[2]);
   strcpy(outfile, "T:DE_LIST");

   if (argc < 4)
   {
      DeadEndUseage();
      return rc;
   }

   if (strchr(address, ':') && strchr(address, '/'))
   {

/* at this point, we need to search the areas structure for
 * passthrough areas that match the address */

      if (Stricmp(argv[3], "DISCONNECT"))
         strcpy(outfile, argv[3]);

      Make5DAddress(sysop, address);
      ASPrintf(NULL,logstring, ".  Finding dead-end passthrough areas for [%s]", address);
      Log(logstring);

      if (count = FindDeadEnds(address, outfile))
      {
         ASPrintf(NULL,logstring, ".  Found %d dead-end areas for [%s]", count, address);
         Log(logstring);

         if (!Stricmp(argv[3], "DISCONNECT"))
         {
            Log("-> Processing dead-end area disconnections");
            ProcessDeadEnds(address, outfile);
            Log("<- Done processing dead-end area disconnections");
         }
      }

      Log(".  Done with all dead-end searching and processing");
   }
   else
   {
      DeadEndUseage();
      return rc;
   }
}
//-

/// RemoveArea
void RemoveArea(char *AreaTag)
{
   BOOL AllDone = FALSE;
   BOOL InTag = FALSE;

   BPTR infh = NULL;
   BPTR outfh = NULL;

   char obuf[1000];

   AFPrintf(NULL,sout,"Deleting TAG %s\n",AreaTag);

   Copy("Fido:DLGMail.ARE","T:DLGMail.TMP");

   infh = Open("T:DLGMail.TMP",MODE_OLDFILE);

   if(!infh) return;

   outfh = Open("Fido:DLGMail.ARE",MODE_NEWFILE);

   if(!outfh)
   {
      Close(infh);
      return;
   }

   while(FGets(infh,obuf,1000))
   {
      char *buf;

      if(AllDone)
      {
         FPuts(outfh,obuf);
         continue;
      }

      buf = strdup(obuf);
      StripSpaces(buf);

      if(!Strnicmp(buf,";",1))
      {
         FPuts(outfh,obuf);
         continue;
      }

      if(!Strnicmp(buf,"TAG",3))
      {
         int c;
         char *t[5];

         if(InTag)
         {
            FPuts(outfh,obuf);
            AllDone = TRUE;
            InTag = FALSE;
            continue;
         }

         c = ArgParse(buf,t,4);

         if(c < 3)
         {
            FPuts(outfh,obuf);
            continue;
         }

         if(!Stricmp(t[1],AreaTag))
         {
            char Dir[512];

            InTag = TRUE;
            ASPrintf(NULL,Dir,"PASS:%s",t[2]);
            DelDir(Dir,NULL);
            continue;
         }
      }

      if(InTag && !Strnicmp(buf,"CONT",4)) continue;

      FPuts(outfh,obuf);
   }

   if(infh) Close(infh);
   if(outfh) Close(outfh);
   return;
}
//-
