#include "DLGAreaFix.h"

#include <link/io.h>

/* upstream handling */

int               HuntForTag(char *, char *, char *);
int               UpstreamRequest(short, short, short, char *, char *,
                                  char *, char *);
struct   area    *FindLastSameDomain(char *, short *, short *, short *,
                                     short *);
int               AddNewArea(char *, char *, int, char *, char *, char *,
                             char *, char *, char *);


/// FindIt
/* this function will return a 1 on an add, a 0 on failure, and a -1 if 
   tag found but class is wrong */
FindIt(char *reqaddress, char *reqclasses, char *tag)
{
   char  domain_dst[30];
   short zone_dst;
   short net_dst;
   short node_dst;
   short point_dst;

   char  potential_address[60];
   int   potential_class;
   char  potential_name[40];
   char  potential_password[40];
   char  potential_file[255];
   char  potential_from[100];
   char  potential_myaddress[100];

   char  desc[80];

   int   rc,mrc=0;

   BPTR  fh;

   if(_VERBOSITY>2)
      AFPrintf(NULL,sout,"*** upstream search ***\n");

   if(!parse5dstring(reqaddress,domain_dst,&zone_dst,&net_dst,&node_dst,&point_dst))
   {
      fh = Open("FIDO:DLGMail.AFX",MODE_OLDFILE);

      if(fh)
      {
         while(1)
         {
            rc=FindFeed(fh,domain_dst,potential_address,&potential_class,potential_name,potential_password,potential_file,potential_myaddress,potential_from);
            potential_from[36]=NULL;
           
            if(rc==0)
            {
               if(_VERBOSITY>2)
                  AFPrintf(NULL,sout,"exhausted potential feeds with no domain match\n");

               Close(fh);

               return mrc;
            }

            if(rc==-1)
            {
               if(_VERBOSITY>2)
                  AFPrintf(NULL,sout,"domain mismatch, continuing\n");

               continue;
            }

            if(rc==1)
            {
               if(_VERBOSITY>2)
                  AFPrintf(NULL,sout,"we have a potential feed... continuing search...\n");

               rc=HuntForTag(potential_file,tag,desc);

               if(rc==0)
               {
                  if(_VERBOSITY>2)
                     AFPrintf(NULL,sout,"can't open %s to search for tag\n",potential_file);
               }

               if(rc==-1)
               {
                  if(_VERBOSITY>2)
                     AFPrintf(NULL,sout,"tag %s not in %d\n",tag,potential_file);
               }

               if(rc==1)
               {
                  Close(fh);

                  if(_VERBOSITY>2)
                     AFPrintf(NULL,sout,"we found tag %s in file %s\n",tag,potential_file);

                  if(!CheckClass(potential_class,reqclasses))
                  {
                     if(_VERBOSITY>2)
                        AFPrintf(NULL,sout,"found the tag but class is inappropriate...\n");
                     
                     return -1;
                  }

                  /* ok, class is OK, found the tag, source, etc... Now do it! */

                  rc=AddNewArea(potential_address,reqaddress,potential_class,potential_name,potential_password,potential_from,desc,tag,potential_myaddress);

                  if(rc==0)
                  {
                     if(_VERBOSITY>2)
                        AFPrintf(NULL,sout,"failed to add new area... bummer!\n");
                     
                     return mrc;
                  }
                  else
                  {
                     if(_VERBOSITY>2)
                        AFPrintf(NULL,sout,"area added...\n");
                     
                     return 1;
                  }
               }
               else
               {
                  if(_VERBOSITY>2)
                     AFPrintf(NULL,sout,"unknown return code %d from HuntForTag()\n",rc);
               }
            }
            else
            {
               if(_VERBOSITY>2)
                  AFPrintf(NULL,sout,"unknown return code %d from FindFeed()...\n",rc);
               Close(fh);
               return mrc;
            }
         }
      }
      else
      {
         if(_VERBOSITY>2)
            AFPrintf(NULL,sout,"Couldn't open the .AFX file for reading\n");
      }
   }
   else
   {
      if(_VERBOSITY>2)
         AFPrintf(NULL,sout,"5d address failure on destination\n");
   }
}
//-

/// FindFeed
/* returns 0 when we find EOF, -1 if domain mismatch, 1 if domain matches */

FindFeed(BPTR fh,char *domain_dst,char *potential_address,int *potential_class,
         char *potential_name, char *potential_password, char *potential_file,
         char *potential_myaddress,char *potential_from)
{
   char  buffer[500]; /* guertin bug, used to be 250 */
   char  token[100];
   char *p;

   char  domain[30];
   short zone,net,node,point;

   *domain=NULL;

   strcpy(potential_address,"");
   strcpy(potential_name,"");
   strcpy(potential_password,"");
   strcpy(potential_file,"");
   *potential_class=555;

   while(FGets(fh,buffer,sizeof(buffer)))
   {
      buffer[strlen(buffer)-1]=NULL;   /* get rid of newline character */

      p=buffer;
      p=stpblk(p);
      
      if(*p==';')
         continue;

      p=stptok(p,token,sizeof(token)," \t");
      p=stpblk(p);

      if(!Stricmp(token,"FEED"))
      {
         p=stptok(p,token,sizeof(token)," \t");
         p=stpblk(p);

         strcpy(potential_address,token);

         if(!parse5dstring(token,domain,&zone,&net,&node,&point))
         {
            if(!Stricmp(domain,domain_dst))
            {
               p=stptok(p,token,sizeof(token)," \t");
               p=stpblk(p);

               *potential_class=atoi(token);

               p=stptok(p,token,sizeof(token)," \t");
               p=stpblk(p);

               strcpy(potential_name,token);

               p=stptok(p,token,sizeof(token)," \t");
               p=stpblk(p);

               strcpy(potential_password,token);

               p=stptok(p,token,sizeof(token)," \t");
               p=stpblk(p);

               strcpy(potential_file,token);

               p=stptok(p,token,sizeof(token)," \t");
               p=stpblk(p);

               strcpy(potential_myaddress,token);

               strcpy(potential_from,p);

               return 1;
            }
            else
            {
               return -1;
            }
         }
         else
         {
            return -1;
         }
      }
      else
      {
         continue;
      }
   }

   return 0;
}
//-

/// HuntForTag
/* returns 0 if file not found, -1 if tag not there, 1 if tagname is present */

HuntForTag(char *potential_file,char *tag, char *desc)
{
   BPTR  fh;
   char  buffer[150];
   char  token[50];
   char *s,*p;

   strcpy(desc,"");

   fh=Open(potential_file,MODE_OLDFILE);

   if(fh)
   {
      while(1)
      {
         s = FGets(fh,buffer,sizeof(buffer));
         
         if(s == NULL)
         {
            Close(fh);
            if(_VERBOSITY>2)
               AFPrintf(NULL,sout,"*** EOF %s ***\n",potential_file);
            return -1;
         }

         buffer[strlen(buffer)-1]=NULL;
   
         if(buffer[strlen(buffer)-1]=='\r')
            buffer[strlen(buffer)-1]=NULL;

         p=buffer;
         p=stpblk(p);
   
         if(*p==';')
            continue;

         p=stptok(p,token,sizeof(token)," \t");
         p=stpblk(p);

         if(!Stricmp(tag,token))
         {
            strncpy(desc,p,40);
            Close(fh);
            
            if(_VERBOSITY>2)
               AFPrintf(NULL,sout,"found %s, desc \"%s\"\n",tag,desc);
            return(1);
         }
      }
   }
   return 0;
}
//-

#define UPREQ "T:AreaFixUpstreamReq"

/// UpstreamRequest
UpstreamRequest(short zone, short net, short node,char *name, char *pw, char *tag, char *from)
{
   BPTR  fh;
   char  address[50];
   char  buffer[150];

   ASPrintf(NULL,address,"%d:%d/%d.0",zone,net,node);

   fh=Open(UPREQ,MODE_NEWFILE);
   if(fh)
   {
      Upper(tag);
      AFPrintf(NULL,fh,"%s\n---\n",tag);
      Close(fh);

      ASPrintf(NULL,buffer,"DLG:SendMsg -n -q -f \"%s\" -s \"%s\" -b \"%s\" -r \"NET %s %s\"",from,pw,UPREQ,address,name);

      if(_VERBOSITY>2)
         AFPrintf(NULL,sout,"%s\n",buffer);
      Log(buffer);

      if(TestPCAddress(address))
         Spawn(Input(),sout, buffer);
      else
         Log(".  Message not sent - Message was to Planet Connect");

      return 1;
   }
   return 0;
}
//-

/// FindLastSameDomain
/* returns 0 if fail, anything else is OK */

struct area *FindLastSameDomain(char *domain,short *zone,short *net,short *node,short *point)
{
   struct area *aa;

   struct area *rc=NULL;
   BOOL  domain_found=FALSE;

   if(a==NULL)
      return 0;
   
   if(a->first_area==NULL)
      return 0;

   for(aa=a->first_area;;aa=aa->next_area)
   {
      if(0==Stricmp(aa->from_organization,domain))
      {
         if(_VERBOSITY>2)
            AFPrintf(NULL,sout,"** domain match searching ross areas **\n");

         domain_found=TRUE;
         rc=aa;

         if(aa->next_area)
            continue;
         else
            return(rc);
      }
      else
      {
         if(_VERBOSITY>2)
            AFPrintf(NULL,sout,"** domain mismatch searching ross areas **\n");

         if(domain_found)
         {
            return(rc);
         }
         else
         {
            if(aa->next_area)
              continue;
            else
               return(rc);
         }
      }
   }
}
//-

/// AddNewArea
AddNewArea(char *potential_address,char *reqaddress,int potential_class,char *potential_name,char *potential_password,char *potential_from,char *desc,char *tag,char *myaddress)
{
   char  domain[40];
   short zone,net,node,point;
   short mzone,mnet,mnode,mpoint;
   char  buffer[100];
   struct area *aa,*bb;
   struct nodenum *nn1, *nn2;
   char *p;
   char  b2[80];
   BPTR  fh;

   if(_VERBOSITY>2)
      AFPrintf(NULL,sout,"-> In AddNewArea()\n");

   if(!parse5dstring(potential_address,domain,&zone,&net,&node,&point))
   {
      /* go ahead and send an areafix message */

      if(1)
      {
         if(_VERBOSITY>2)
            AFPrintf(NULL,sout,"address parsed OK");

         /**** build new area here ****/

         aa=new(sizeof(struct area));

         if(_VERBOSITY>2)
            AFPrintf(NULL,sout,"new() returned %d\n",(int)aa);

         if(aa)
         {
            aa->first_nodenum=0;
            aa->next_area=0;
            aa->passthru=1;
            aa->link=0;
            aa->alias=0;
            aa->areanum=0;
            aa->class=potential_class;

            ASPrintf(NULL,buffer,"PASS:%s",tag);
            
            if(strlen(buffer)>MAX_STR)
               buffer[MAX_STR-1]=NULL;

            /* new ====> */
            FixSlashes(buffer);

            if(_VERBOSITY>2)
               AFPrintf(NULL,sout,"creating directory\n");

            fh=CreateDir(buffer);
            
            if(fh)
            {
               UBYTE clock[10];

               UnLock(fh);
            
               if(_VERBOSITY>2)
                  AFPrintf(NULL,sout,"Directory created...\n");
               
               Log(".  New directory created for area");

               getclk(clock);

               ASPrintf(NULL,b2,"TAG: %s CREATED: %d",tag,clock[1]*365+clock[2]*30+clock[3]);

               SetComment(buffer,b2);
            }

            strcat(buffer,"/");

            strcpy(aa->path,buffer);

            strncpy(aa->name,tag,MAX_STR);

            Upper(aa->name);
            Upper(aa->path);

            Log(buffer);
            Log(aa->path);
            Log(".  preceeding line is what is stored in magic list");
            aa->description=0;

            if(*desc)
            {
               p=(void *)calloc(40,1);

               if(p)
               {
                  strncpy(p,desc,40);
                  aa->description=p;
               }
            }

            if(!parse5dstring(myaddress,buffer,&mzone,&mnet,&mnode,&mpoint))
            {
               strncpy(aa->from_organization,buffer,MAX_STR);
               aa->from_zone=mzone;
               aa->from_net=mnet;
               aa->from_node=mnode;
               aa->from_point=mpoint;

               nn1=new(sizeof(struct nodenum));
            
               if(nn1)
               {
                  nn1->next_nodenum=0;
                  nn1->strip=0;
                  strcpy(nn1->from_organization,aa->from_organization);
                  nn1->from_zone=aa->from_zone;
                  nn1->from_net =aa->from_net;
                  nn1->from_node=aa->from_node;
                  nn1->from_point=aa->from_point;

                  /* fill in potential feed info here */

                  parse5dstring(potential_address,buffer,&zone,&net,&node,&point);
                  strncpy(nn1->organization,buffer,MAX_STR);
                  nn1->zone=zone;
                  nn1->net=net;
                  nn1->node=node;
                  nn1->point=point;

                  nn2=new(sizeof(struct nodenum));

                  if(nn2)
                  {
                     nn1->next_nodenum=nn2;
                     aa->first_nodenum=nn1;

                     nn2->next_nodenum=0;
                     nn2->strip=0;
                     strcpy(nn2->from_organization,aa->from_organization);
                     nn2->from_zone=aa->from_zone;
                     nn2->from_net =aa->from_net;
                     nn2->from_node=aa->from_node;
                     nn2->from_point=aa->from_point;

                     /* fill in potential downstream info here */

                     parse5dstring(reqaddress,buffer,&zone,&net,&node,&point);
                     strncpy(nn2->organization,buffer,MAX_STR);
                     nn2->zone=zone;
                     nn2->net=net;
                     nn2->node=node;
                     nn2->point=point;

                     /* theoretically, all the magic shit is filled in
                        correctly at this point... now all we need to
                        do is to insert it into the existing linked list */

                     bb=FindLastSameDomain(domain,&mzone,&mnet,&mnode,&mpoint);

                     if(bb)
                     {
                        if(_VERBOSITY>2)
                           AFPrintf(NULL,sout,"linking new area shit\n");

                        aa->next_area=bb->next_area;
                        bb->next_area=aa;

                        if(UpstreamRequest(nn1->zone,nn1->net,nn1->node,
                           potential_name,potential_password,tag,potential_from))
                        {
                           if(_VERBOSITY>2)
                              AFPrintf(NULL,sout,"upstream request message sent\n");
                        }

                        free(p);
                        return 1;
                     }
                  }
               }
            }
         }
      }
      else
      {
         if(_VERBOSITY>2)
            AFPrintf(NULL,sout,"problem sending upstream areafix message\n");
      }
   }
   else
   {
      if(_VERBOSITY>2)
         AFPrintf(NULL,sout,"problems parsing 5d string\n");
   }

   return 0;
}
//-


