#include <exec/types.h>
#include <string.h>
#include <stdlib.h>

#include <dlg/msg.h>
#include <dlg/file.h>

#include <link/io.h>
#include <link/config.h>
#include <link/user.h>

#include <proto/dlg.h>
#include <proto/dos.h>

#include <pragmas/dlg.h>

extern   BPTR                 sout;

extern   char                 Ext[4];

extern   int                  AreaType;

extern   struct   Library    *DLGBase;
extern   struct   USER_DATA   UserDat;

extern   void  Apply_Template(struct Msg_Area *ma);
extern   void  Edit_Area(struct Msg_Area *);
extern   void _CXBRK(void);
extern   BOOL  Change_Path(struct Msg_Area *, BOOL );

void  Set_Auto_Access(struct Msg_Area *);
void  Set_Write_Access(struct Msg_Area *);
void  Set_Kill_Access(struct Msg_Area *);
void  Set_Forward_Access(struct Msg_Area *);
void  Set_Copy_Access(struct Msg_Area *);
void  Set_Edit_Access(struct Msg_Area *);
void  Set_Sysop_Access(struct Msg_Area *);
BOOL  IsAreaValid( SHORT );
BYTE  Sort_List(char *name);

/// Add_Area
BYTE Add_Area(void)
{
   long              t;

   struct   Msg_Area ma;

/// Get Area Number
   ma.Number = iinput(1,9999,0, "Enter area number for new area (RETURN to list current areas) %a7-> ");
   TwoLines();

   if(0 == ma.Number)
   {
      ListAreas(NULL,&UserDat,AreaType,0);
      ma.Number = iinput(1,9999,0, "Enter area number for new area (RETURN to abort) %a7-> ");
      TwoLines();
   }

   if(0 == ma.Number)
   {
      AFPrintf(&UserDat,sout,"Aborted ...\n\n");
      return(0);
   }
//-
/// Check if area exists
   if(ReadArea(ma.Number,&ma,AreaType))
   {
      AFPrintf(&UserDat,sout, "%a3Area already exists!\n\n%a7Aborted ...\n\n");
      return(0);
   }
//-
/// Get area name
   t = DLGInput(NULL,ma.Name,NULL,33,33,3, "%a3Enter name of new %s area %a7-> ",(AreaType ? "file" : "msg"));
   OneLine();

   if(t == 0) { AFPrintf(&UserDat,sout,"Aborting ... \n\n");   return(0); }
//-

   TwoLines();

   if (finput(0, "%a3Would you like to import a template? %a7-> "))
   {
      OneLine();
      Apply_Template(&ma);
      Edit_Area(&ma);
      return(1);
   }

   TwoLines();
   ma.Flag = 0;

///   Auto-access
   t = finput(1, "Is this an auto-access area? %a7-> ");
   TwoLines();

   if(t)
   {
      ma.Flag = ma.Flag | AUTO_ACCESS_AREA;
      Set_Auto_Access(&ma);
   }
   else
   {
      ma.llevel = 1;
      ma.ulevel = 1;
   }
//-

   ma.lwrite = ma.lkill = ma.lforward = ma.lcopy = ma.ledit = ma.lsysop = 1;
   ma.uwrite = ma.ukill = ma.uforward = ma.ucopy = ma.uedit = ma.usysop = 1;

   Set_Write_Access(&ma);     // upload or write
   Set_Kill_Access(&ma);      // kill
   Set_Forward_Access(&ma);   // forward or download
   Set_Copy_Access(&ma);      // copy or xfer

   if(AreaType == 0) Set_Edit_Access(&ma);

   Set_Sysop_Access(&ma);

///   Alias flag
   if (finput(0, "Allow aliases (handles)? %a7-> "))  ma.Flag |= HANDLES_AREA;
   OneLine();
//-
///   Signature flag
   if (finput(1, "Use signatures? %a7-> "))  ma.Flag |= SIGNATURE_AREA;
   OneLine();
//-
///   Echomail flag
   if(AreaType == 0) // msg only
   {
      if (finput(0, "Will this be an echomail area? %a7-> "))  ma.Flag |= ECHO_AREA;
      OneLine();
   }
//-
///   Validation flag
   if(AreaType == 1) // file only
   {
      if (finput(0, "Will uploaded files require validation? %a7-> "))  ma.Flag |= VALIDATION_AREA;
      OneLine();
   }
//-
///   FREQ flag
   if(AreaType == 1) // file only
   {
      if (finput(0, "File Requestable (FREQ) area? -> "))   ma.Flag |= FREQ_AREA;
      OneLine();
   }
//-
///   Temp_Download flag
   if(AreaType == 1) // file only
   {
      if (finput(0, "Copy files before downloading? %a7-> "))  ma.Flag |= TEMP_DOWNLOAD;
      OneLine();
   }
//-

   strcpy(ma.origin,"");

///   If echo area, set up flags and origin, otherwise check for newsgroup flag and set up newsgroup
   if(AreaType == 0) // msg only
   {
      if (ma.Flag & ECHO_AREA)
      {
///      Set up echo area
         if (finput(1, "Hide SEEN-BY kludges? %a7-> "))  ma.Flag |= HIDE_SEENBY;
         OneLine();

         DLGInput(NULL, ma.origin,NULL,74,74,0, "Custom Origin line (return for default) %a7-> ");
         OneLine();
//-
      }
      else
      {
///      Netmail Flag
         if (finput(0, "Is this a Netmail area? %a7-> "))   ma.Flag |= NETMAIL_AREA;
         OneLine();
//-
///      Newsgroup flag
         if(!(ma.Flag & NETMAIL_AREA))
         {
            if (finput(0, "Is this a UseNet newsgroup? %a7->"))
               ma.Flag |= NEWSGROUP_AREA;

            OneLine();
         }
//-
      }
   }
//-

///   Message processor batch file
   if(AreaType == 0) // msg only
   {
      DLGInput(NULL, ma.processor,NULL,11,11,0, "Message processor batch file  DLGConfig:Batch/");
      OneLine();
   }
//-
///   Capacity /  Validation area
   if(AreaType == 0) // msg area
   {
      ma.Capacity   = iinput(10,9000,100,"How many messages do you wish to store in this area? %a7-> ");
      OneLine();
   }
   else  // file area
   {
      if(ma.Flag & VALIDATION_AREA)
      {
         BOOL  b  =  FALSE;

         while(!b)
         {
            ma.Capacity   = iinput(0,9999,0, "Which file area do unvalidated files get sent to? %a7-> ");
            OneLine();

            if(ma.Capacity != 0)
               b = IsAreaValid(ma.Capacity);
            else
               b = TRUE;
         }
      }
   }
//-
///   Renumber
   if(AreaType == 0)
   {
      ma.UpperLimit = (SHORT)iinput(10,9000,500, "How many messages will trigger a renumber? %a7-> ");
      TwoLines();
   }
//-
///   Character sets
   if(AreaType == 0)
   {
      ListSets(255);
      ma.savecharset = iinput(1,255,0, "Character set to store messages in [RETURN for default] %a7-> ");
      OneLine();
   }
//-
///   Alt file path
   if(AreaType == 1) // file only
   {
      Change_Path(&ma, FALSE );
      OneLine();
   }
//-

   Edit_Area(&ma);
   return(1);
}
//-

/// Set_Auto_Access
void Set_Auto_Access(struct Msg_Area *ma)
{
   long l   =  ma->llevel;
   long u   =  ma->ulevel;

   if((l == 1) && (u == 1))   u = 255;

   ma->llevel = iinput(0,255,l, "\tUser level required (lower) %a7-> ");
   OneLine();

   ma->ulevel = iinput(ma->llevel,255, u, "\tUser level required (upper) %a7-> ");
   TwoLines();
}
//-
/// Set_Write_Access
void Set_Write_Access(struct Msg_Area *ma)
{
   BOOL  b;
   long l   =  ma->lwrite;
   long u   =  ma->uwrite;

   b = (ma->Flag & AUTO_ACCESS_AREA);

   if(l == u){l = (b ? ma->llevel : 1) ; u = 255;}

   ma->lwrite=iinput( (b ? ma->llevel : 1), (b ? ma->ulevel : 255), l, "\tLevel required to %s (lower) %a7-> ",(AreaType ? "upload files" : "write messages"));
   OneLine();

   ma->uwrite=iinput(ma->lwrite, (b ? ma->ulevel : 255), u, "\tLevel required to %s (upper) %a7-> ",(AreaType ? "upload files" : "write messages"));
   TwoLines();
}
//-
/// Set_Kill_Access
void Set_Kill_Access(struct Msg_Area *ma)
{
   BOOL  b;
   long l   =  ma->lkill;
   long u   =  ma->ukill;

   b = (ma->Flag & AUTO_ACCESS_AREA);

   if(l == u){l = (b ? ma->llevel : 1) ; u = 255;}

   ma->lkill=iinput( (b ? ma->llevel : 1), (b ? ma->ulevel : 255), l, "\tLevel required to kill %s (lower) %a7-> ",(AreaType ? "files" : "messages"));
   OneLine();

   ma->ukill=iinput(ma->lkill, (b ? ma->ulevel : 255), u, "\tLevel required to kill %s (upper) %a7-> ",(AreaType ? "files" : "messages"));
   TwoLines();
}
//-
/// Set_Forward_Access
void Set_Forward_Access(struct Msg_Area *ma)
{
   BOOL  b;
   long l   =  ma->lforward;
   long u   =  ma->uforward;

   b = (ma->Flag & AUTO_ACCESS_AREA);

   if(l == u){l = (b ? ma->llevel : 1) ; u = 255;}

   ma->lforward=iinput( (b ? ma->llevel : 1), (b ? ma->ulevel : 255), l, "\tLevel required to %s (lower) %a7-> ",(AreaType ? "download files" : "forward messages"));
   OneLine();

   ma->uforward=iinput(ma->lforward, (b ? ma->ulevel : 255), u, "\tLevel required to %s (upper) %a7-> ",(AreaType ? "download files" : "forward messages"));
   TwoLines();
}
//-
/// Set_Copy_Access
void Set_Copy_Access(struct Msg_Area *ma)
{
   BOOL  b;
   long l   =  ma->lcopy;
   long u   =  ma->ucopy;

   b = (ma->Flag & AUTO_ACCESS_AREA);

   if(l == u){l = (b ? ma->llevel : 1) ; u = 255;}

   ma->lcopy = iinput( (b ? ma->llevel : 1), (b ? ma->ulevel : 255), l, "\tLevel required to %s (lower) %a7-> ",(AreaType ? "transfer files" : "copy/move messages"));
   OneLine();

   ma->ucopy = iinput(ma->lcopy, (b ? ma->ulevel : 255), u, "\tLevel required to %s (upper) %a7-> ",(AreaType ? "transfer files" : "copy/move messages"));
   TwoLines();
}
//-
/// Set_Edit_Access
void Set_Edit_Access(struct Msg_Area *ma)
{
   BOOL  b;
   long l   =  ma->ledit;
   long u   =  ma->uedit;

   if(AreaType) return;

   b = (ma->Flag & AUTO_ACCESS_AREA);

   if(l == u){l = (b ? ma->llevel : 1) ; u = 255;}

   ma->ledit=iinput( (b ? ma->llevel : 1), (b ? ma->ulevel : 255), l, "\tLevel required to edit messages (lower) %a7-> ");
   OneLine();

   ma->uedit = iinput(ma->ledit, (b ? ma->ulevel : 255), u, "\tLevel required to edit messages (upper) %a7-> ");
   TwoLines();
}
//-
/// Set_Sysop_Access
void Set_Sysop_Access(struct Msg_Area *ma)
{
   BOOL  b;
   long l   =  ma->lsysop;
   long u   =  ma->usysop;

   if(l == u == 1){ l = 255; u = 255;}

   b = (ma->Flag & AUTO_ACCESS_AREA);

   ma->lsysop=iinput((b ? ma->llevel : 1), (b ? ma->ulevel : 255), l, "\tLevel required for Sysop access (lower) %a7-> ");
   OneLine();

   ma->usysop=iinput(ma->lsysop, (b ? ma->ulevel : 255), u, "\tLevel required for Sysop access (upper) %a7-> ");
   TwoLines();
}
//-


/// IsAreaValid
BOOL  IsAreaValid( SHORT Area)
{
   char                 t[256];
   int                  i;
   struct   Msg_Area   *a  =  NULL;
   ULONG                l  =  0;


   ASPrintf(NULL,t,"%s:Area.BBS",(AreaType ? "FILE" : "MSG"));

   if(-1 == FileSize(t,&l))   return( FALSE );

   a  =  calloc(1,l);

   if(!a) return( FALSE );

   if(-1 == GetFirstStruct(t,(char *)a,l))   return( FALSE );

   for(i = 0; i < (l/sizeof(struct Msg_Area)); i++)
   {
      if(a[i].Number == Area)   { free(a); a = NULL; return( TRUE ); }
   }

   free(a); a = NULL;
   return( FALSE );
}
//-
/// New_Area()
void New_Area(struct Msg_Area *ma)
{
   BOOL  b     =  FALSE;

   BPTR  lock  =  NULL;
   BPTR  fh    =  NULL;

   char  t[256];
   char  AreaFile[256];

   ASPrintf(NULL,t,"%s:%ld",(AreaType ? "FILE" : "MSG"), ma->Number);

/// Create area directory
   if (!Exists(t))
   {
      if (!(lock=CreateDir(t)))
      {
         AFPrintf(&UserDat,sout, "%a1ERROR %a3in New_Area(): Could not create directory!\n\n");
         return;
      }

      UnLock(lock);  lock = NULL;
      AFPrintf(&UserDat,sout, "%a3Directory created successfully\n\n");
   }
//-

   ASPrintf(NULL,AreaFile,"%s:Area.BBS",(AreaType ? "FILE" : "MSG"));

   fh = Open(AreaFile, MODE_READWRITE);

   if (!fh)
   {
      AFPrintf(&UserDat,sout, "%a1ERROR %a3in New_Area(): Could not access AREA.BBS!\n\n");
      return;
   }

   Seek(fh,0L,OFFSET_END);
   Write(fh,ma,sizeof(struct Msg_Area));
   Close(fh);  fh = NULL;

   AFPrintf(&UserDat,sout, "%a3Area successfully added.\n\n");

   ASPrintf(NULL,t,"%s:%ld/User.MSG",(AreaType ? "FILE" : "MSG"),ma->Number);

   fh = Open(t,MODE_NEWFILE);
   Close(fh);  fh = NULL;

   if (ma->Flag & AUTO_ACCESS_AREA)
   {
      b = finput(1, "%a3Add to users' auto-access lists? %a7-> ");
      TwoLines();
      if (b)  AddGlobalArea(ma->ulevel,ma->llevel,ma->Number,AreaType,0,Ext);
   }

   Sort_List(AreaFile);

   if (finput(0,"Add area to SIGs?"))
   {
      BPTR sfh = NULL;

      struct SIG_Def sdef;

      AFPrintf(NULL, sout, "\n");

      ASPrintf(NULL, t, "DLGConfig:Sigs/Sigs.%s",(AreaType ? "file" : "msg"));
      sfh = Open(t, MODE_OLDFILE);

      if(sfh)
      {
         char sigtemp[256];

         while(Read(sfh,&sdef,sizeof(struct SIG_Def)) == sizeof(struct SIG_Def))
         {
            ASPrintf(&UserDat,sigtemp, "%a3Add to SIG %a5[%a7%s%a5]%a7?",sdef.name);

            if (finput(0, "%a3Add to SIG %a5[%a7%s%a5]%a7?",sdef.name))
            {
               BPTR sffh = NULL;
               char sigfilename[256];

               ASPrintf(NULL,sigfilename,"DLGConfig:SIGS/%s.%s",sdef.name, (AreaType ? "file" : "msg"));

               sffh = Open(sigfilename,MODE_READWRITE);

               if(sffh)
               {
                  Seek(sffh,0,OFFSET_END);
                  Write(sffh,ma,sizeof(struct Msg_Area));
                  Close(sffh); sffh = NULL;
                  Sort_List(sigfilename);
                  AFPrintf(NULL,sout,"... added.\n");
               }
               else
               {
                  AFPrintf(NULL,sout,"... failed.\n");
               }
            }
            else
            {
               AFPrintf(NULL,sout,"\n");
            }
         }

         Close(sfh);
      }
   }
   else
   {
      AFPrintf(NULL, sout, "\n");
   }

   return;
}
//-
/// Sort_List
BYTE Sort_List(char *name)
{
   ULONG            readsize;
   long             numrecords;
   struct Msg_Area *carea;
   struct Msg_Area *parea;
   struct Msg_Area *arealist;
   struct Msg_Area  temparea;

   BPTR             fp;
   char             filename[128];


   FileSize(name, &readsize);

   if ((fp = Open(name, MODE_READWRITE)) == NULL )
   {
      AFPrintf(&UserDat,sout, "%a1Error! %a3Can't open %s!\n",filename);
      return(1);
   }

   arealist = calloc(1,readsize);

   if (!arealist)
   {
      AFPrintf(&UserDat,sout, "%a1Error! %a3Can't allocate memory!\n");
      Close(fp);  fp = NULL;
      _CXBRK();
   }

   numrecords = readsize / sizeof(struct Msg_Area);

   if ((Read(fp, arealist, readsize)) != readsize)
   {
      Close(fp);  fp = NULL;
      return(1);
   }

   for(carea = arealist+1; (carea - arealist) < numrecords; carea++)
   {
      parea = carea - 1;

      if (carea->Number < parea->Number)
      {
         movmem(parea,    &temparea, sizeof(struct Msg_Area));
         movmem(carea,     parea,    sizeof(struct Msg_Area));
         movmem(&temparea, carea,    sizeof(struct Msg_Area));
         if (carea > arealist+1)  carea -= 2;
      }
   }

   Seek(fp, 0, OFFSET_BEGINNING);
   Write(fp, arealist, readsize);
   Close(fp);  fp = NULL;

   free(arealist);
   return(1);
}
//-

