#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 <time.h>


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

#include <HBBS/ANSI_Codes.h>
#include <HBBS/Defines.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: MoveFile "RELEASE_STR;

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

struct BBSGlobalData *BBSGlobal=NULL;
struct NodeData *N_ND=NULL;
int N_NodeNum=-1;
char outstr[BIG_STR]; // temp string for displaying text..

long __stack=16384;
// for global use..

int gargc;
char **gargv;

  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 DoorMain( void )
{
  struct ConfData *Conf=NULL;
  V_BIGNUM ConfNum;
  struct List *PathList=NULL;
  struct Node *node;
  BOOL Done=FALSE,Error=FALSE;
  struct InfoData ID;
  BPTR FL;
  struct FileInfoBlock FB;
  LONG nextparam=2;
  char fromname[1024],toname[1024];
  char dizfromname[1024],diztoname[1024];
  char *filename;
  
  
  filename = gargv[nextparam+1];
  
  if (UserAround) DOOR_WriteText(ANSI_RESET);

  // FromName = node's playpen dir + filename
   
  strcpy(fromname,N_ND->NodeSettings.NodePlayPen);
  strcat(fromname,filename);

  if (FL=Lock(fromname,ACCESS_READ))
  {
    if (Examine(FL,&FB)) Done=TRUE;
    UnLock(FL);                  
  }

  if (Done)
  {
    Done=FALSE;

    if (stricmp("BAD",gargv[nextparam])==0)
    {
      if (Conf=FindConf())
      {
        PathList=Conf->BadFiles;
      }
      nextparam++;
    }
    else
    {
      if (stricmp("NEEDDIZ",gargv[nextparam])==0)
      {
        if (Conf=FindConf())
        {
          PathList=Conf->NeedDIZ;
        }
        nextparam++;
      }
      else
      {
        if (stricmp("HOLD",gargv[nextparam])==0)
        {
          if (Conf=FindConf())
          {
            PathList=Conf->HoldFiles;
          }
          nextparam++;
        }
        else
        {
          if (stricmp("PARTUPLOAD",gargv[nextparam])==0)
          {
            if (Conf=FindConf())
            {
              PathList=Conf->PartUpload;
            }
            nextparam++;
          }
          else
          {
            if (sscanf(gargv[nextparam],"%ld",&ConfNum))
            {
              if (ValidConfNum(ConfNum))
              {
                Conf=(struct ConfData *)GetNode(BBSGlobal->ConfList,ConfNum-1);
                PathList=Conf->Upload;
              }
              else
              {
                if (UserAround) DOOR_WriteText("Invalid Conference\r\n");
              }
              nextparam++;
            }
          }
        }
      }
    }

    if (Conf && PathList)
    {
      for (node=PathList->lh_Head ; node->ln_Succ && !Error && !Done ; node=node->ln_Succ)
      {
//        sprintf(outstr,"Checking path: %s\r\n",node->ln_Name);
//        DOOR_SysopText(outstr);
        if (PathOK(node->ln_Name))
        {

          if (FL=Lock(node->ln_Name,ACCESS_READ))
          {
            if (Info(FL,&ID))
            {
              if (ID.id_DiskState == ID_VALIDATED)
              {
                if ( (ID.id_NumBlocks-ID.id_NumBlocksUsed) > (FB.fib_Size / ID.id_BytesPerBlock))
                {
                  strcpy(toname,node->ln_Name);
                  strcat(toname,gargv[nextparam]);
                  nextparam++;
                  if (!PathOK(toname)) // file exist in dest dir ?
                  {

                    // try a rename first as it's tonnes quicker!
                    if (!(Done=Rename(fromname,toname)))
                    {
                      // if that fails then copy it
                      if (Done=HBBS_CopyFile(fromname,toname,32768)) // *C* copy buffer file size
                      {
                        // and if that worked, delete the first file..
                        DeleteFile(fromname);
                      }
                    }
                    if (Done)
                    { 
                    
                      sprintf(outstr,"Moved File, Destination: %s Source: %s",toname,fromname);
                      HBBS_AddToCallersLog(outstr);
                      
                              
                      if (nextparam<gargc)
                      {
                        if (stricmp(gargv[nextparam],"MOVEDIZ")==0)
                        {
                          nextparam++;
                          strcpy(diztoname,node->ln_Name);
                          strcat(diztoname,gargv[nextparam]);
                          strcat(diztoname,".DIZ");

                          sprintf(dizfromname,"%sWork/%s.DIZ",N_ND->NodeLocation,gargv[nextparam]);

                          HBBS_CopyFile(dizfromname,diztoname,32768);
                        }
                      }
                      if (UserAround)
                      {
                        // tell the user one thing..

                        DOOR_WriteText(ANSI_FG_YELLOW "File moved OK!\r\n");

                        // and the sysop something else as well!

                        sprintf(outstr,"File Moved To %s\r\n",toname);
                        DOOR_SysopText(outstr);
                      }
                    }
                  }
                  else Error=TRUE;
                }
              }
            }
            UnLock(FL);
          }
        }
      }
    }
    if (!Done || Error)
    {
      // could not put the file in a dir, move it to HBBS:LostFIles and record
      // this in error log..

      sprintf(outstr,"Could not move %s to any Upload/BAD/HOLD Path!\nIt *MAY* now be in HBBS:LostFiles",filename);
      HBBS_LogError(BBSGlobal->ErrorLogFile,ERR_GENERAL,outstr,TYPE_WARNING);
      if (UserAround)
      {
        DOOR_WriteText("Could Not Move File, Trying To Move It To \"HBBS:LostFiles\"\r\n"
                       "Check your upload paths are valid\r\n");
      }
      strcpy(toname,"HBBS:LostFiles/");
      strcat(toname,filename);

      if (!(Done=Rename(fromname,toname)))
      {
        // if that files then copy it
        if (Done=HBBS_CopyFile(fromname,toname,32768))
        {
          // and if that worked, delete the first file..
          DeleteFile(fromname);
        }
      }


      if (Done && UserAround)
      {
        DOOR_WriteText("Moved File To HBBS:LostFiles OK\r\n");
      }
    }
  }                                                
  
  if (!Done && UserAround) 
  {
    sprintf(outstr,"MoveFile Could not locate file (%s)",filename);
    HBBS_LogError(BBSGlobal->ErrorLogFile,ERR_GENERAL,outstr,TYPE_WARNING);
  }
}

int main(int argc,char **argv)
{
  gargc=argc;
  gargv=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("MoveFile");

  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();
    }
  }
  cleanup(0);
}
