// skeleton code for writing a new door

#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>
#include <HBBS/hbbscommon_pragmas.h>
#include <HBBS/Hbbsnode_protos.h>
#include <HBBS/Hbbsnode_pragmas.h>

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

struct BBSGlobalData *BBSGlobal=NULL;
struct NodeData *N_ND=NULL;
int N_NodeNum=-1;

char *FL_PARAM=NULL;
char *FL_LIST=NULL;
char tmpstr[BIG_STR];
V_SMALLNUM LinesOutput=0;
BOOL Quit=FALSE,NonStop=FALSE;
V_BIGNUM CurrentFileNumber=0;


#define BUFFERSIZE 1024  // *C* Increase to 32k

ULONG FH;
ULONG FL;
UBYTE Buffer[BUFFERSIZE];
ULONG BytesInBuffer;
ULONG BufferOffset;

#define DIR_FORWARDS TRUE
#define DIR_REVERSE FALSE

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 ErrorOpening( void )
{
  DOOR_WriteText("Error Opening List File!\r\n");
}

void strpad(char *buffer, int requiredlen, UBYTE PadChar)
{
  int many;
  int loop;
  int clen=strlen(buffer);

  if (clen<requiredlen)
  {
    many=requiredlen-clen;
    for (loop=0;loop<=many;loop++) buffer[clen+loop]=PadChar;
    buffer[requiredlen]=0;
  }
}

void PrintLine( char *buffer)
{
  // Depending on the it at the start of the buffer different things happen to the
  // output of the reset of the buffer..

  if (buffer[1]==' ')
  {
    switch (buffer[0])
    {
      case 'F' :
        CurrentFileNumber++;
        DOOR_WriteText(ANSI_RESET ANSI_FG_BLUE);
        sprintf(tmpstr,"-- "ANSI_FG_YELLOW"["ANSI_FG_WHITE" %d "ANSI_FG_YELLOW"]"ANSI_FG_WHITE" - "ANSI_FG_YELLOW"["ANSI_FG_WHITE" %s "ANSI_FG_YELLOW"]"ANSI_FG_WHITE" - "ANSI_FG_YELLOW"["ANSI_FG_WHITE" Node %d "ANSI_FG_YELLOW"]"ANSI_FG_BLUE" ",CurrentFileNumber,BBSGlobal->BBSName,N_ND->NodeNum);
        strpad(tmpstr,79+60,'-'); // +60 for the ansi!
        strcat(tmpstr,"\r\n");
        DOOR_WriteText(tmpstr);

        // first part of line needs to be CYAN

        DOOR_WriteText(ANSI_FG_CYAN);
        strNcpy(tmpstr,&buffer[2],34);
        DOOR_WriteText(tmpstr);

        // last part of line needs to be WHITE

        DOOR_WriteText(ANSI_FG_WHITE);
        strfcpy(tmpstr,&buffer[2],34); // index at 0, so use 34 instead of 35 for the 34th char..
        DOOR_WriteText(tmpstr);
        DOOR_WriteText("\r\n");
        LinesOutput+=2;
        break;
      case 'I' :
        DOOR_WriteText(ANSI_FG_WHITE);
        DOOR_WriteText(&buffer[2]);
        DOOR_WriteText("\r\n");
        LinesOutput++;
        break;
      case 'X' :
        strpad(buffer,81,' '); // make sure it's 81 chars long.. 79 are printed..
        DOOR_WriteText(ANSI_BG_BLUE ANSI_FG_WHITE);
        DOOR_WriteText(&buffer[2]);
        DOOR_WriteText("\r\n");
        DOOR_WriteText(ANSI_RESET);
        LinesOutput++;
        break;
      case 'P' :
        DOOR_WriteText(ANSI_RESET);
        DOOR_WriteText(&buffer[2]);
        DOOR_WriteText("\r\n");
        DOOR_WriteText(ANSI_RESET);
        LinesOutput++;
        break;
      case 'T' :
        if (strlen(buffer)>=25)
        {
          strNcpy(tmpstr,&buffer[2],25);
          DOOR_WriteText(tmpstr);
          DOOR_WriteText(ANSI_FG_YELLOW);
          strNcpy(tmpstr,&buffer[27],8);
          DOOR_WriteText(tmpstr);
          DOOR_WriteText(ANSI_FG_WHITE);
          DOOR_WriteText(&buffer[35]);
          DOOR_WriteText("\r\n");
          LinesOutput++;
        }
        break;
      case 'N' :
        if (strlen(buffer)>=25)
        {
          strNcpy(tmpstr,&buffer[2],25);
          DOOR_WriteText(tmpstr);
          DOOR_WriteText(ANSI_FG_GREEN);
          strNcpy(tmpstr,&buffer[27],8);
          DOOR_WriteText(tmpstr);
          DOOR_WriteText(ANSI_FG_WHITE);
          DOOR_WriteText(&buffer[35]);
          DOOR_WriteText("\r\n");
          LinesOutput++;
        }
        break;
    }
  }
}

void ScreenPausePrompt( void )
{
  V_BOOL Help;

  if (!NonStop)
  {
    do
    {
      Help=FALSE;
      strcpy(N_ND->CharsAllowed,"YyNnCcAaFfRr?Qq");
      DOOR_WriteText(ANSI_RESET "More "ANSI_FG_YELLOW"["ANSI_FG_WHITE"Y/N/C/A/F/R/?"ANSI_FG_YELLOW"]"ANSI_FG_WHITE " : ");
      DOOR_GetLine(GL_EDIT|GL_DISPLAY|GL_USECHARS|GL_IMMEDIATE|GL_NORETURN,'\0',1,0,NULL);
      if (N_ND->OnlineStatus==OS_ONLINE)
      {
        DOOR_WriteText("\r[K"); // erase line
        if (stricmp("F",N_ND->CurrentLine)==0)
        {
          DOOR_WriteText(ANSI_FG_CYAN "Enter Filenames To Tag > "ANSI_FG_WHITE);
          DOOR_GetLine(GL_EDIT|GL_DISPLAY,'\0',0,0,NULL);
          if (N_ND->OnlineStatus==OS_ONLINE)
          {
            RemoveSpaces(N_ND->CurrentLine);
            if (N_ND->CurrentLine[0])
            {
              strcpy(tmpstr,N_ND->CurrentLine);
              DOOR_UserDoor("A",tmpstr);
              Help=TRUE;
            }
          }
        }
        else
        if (stricmp("R",N_ND->CurrentLine)==0)
        {
          DOOR_WriteText(ANSI_FG_CYAN"Enter FileNumbers To Tag > "ANSI_FG_WHITE);
          DOOR_GetLine(GL_EDIT|GL_DISPLAY,'\0',0,0,NULL);
          Help=TRUE;
        }
        else
        if (stricmp("C",N_ND->CurrentLine)==0)
        {
          DOOR_WriteText(ANSI_CLS);
        }
        else
        if ((stricmp("N",N_ND->CurrentLine)==0) || (stricmp("Q",N_ND->CurrentLine)==0))
        {
          Quit=TRUE;
        }
        else
        if (stricmp("A",N_ND->CurrentLine)==0)
        {
          NonStop=TRUE;
        }
        if (stricmp("?",N_ND->CurrentLine)==0)
        {
          DOOR_WriteText(ANSI_FG_CYAN
                         "?  -  This Help Page\r\n"
                         "C  -  Clear Screen And Continue\r\n"
                         "N/Q-  No More Please (QUIT)\r\n"
                         "A  -  Display All of remaining files (same as /X's NS)\r\n"
                         "F  -  Flag File By NAME\r\n"
                         "R  -  Flag File By NUMBER\r\n");
          Help=TRUE;
        }
      }
    }
    while ((N_ND->OnlineStatus==OS_ONLINE) && (Help));
  }
  LinesOutput=0;
}


void GetData( void )
{
  BytesInBuffer=Read(FH,Buffer,BUFFERSIZE);
  BufferOffset=0;
}

void FileList(BOOL direction,char *listname,int fromdays, int todays)
{
  BOOL Done=FALSE;
  int LinePos;
  char filename[BIG_STR];
  UBYTE LineBuffer[82];

  // *C* Copy File To Ram HERE and update FILENAME with the name of the file in ram:
  strcpy(filename,listname);

  DOOR_WriteText(ANSI_RESET);

  if (FL=Lock(filename,ACCESS_READ))
  {
    if (FH=OpenFromLock(FL))
    {
      // Fetch some data to process..
      GetData();
      if (BytesInBuffer>0) // Get Some ?
      {
        LinesOutput=0;
        while ((N_ND->OnlineStatus==OS_ONLINE) && (!Done) && (!Quit))
        {
          // Ok, get a line of text, not exceeding more than 80 chars long.

          LinePos=0;
          while ((BytesInBuffer>0) && (Buffer[BufferOffset]!='\n') && (LinePos<=81))
          {
            LineBuffer[LinePos++]=Buffer[BufferOffset++];

            // Fetch More Data ?
            if (BufferOffset>=BytesInBuffer)
            {
              GetData();
            }
          }
          if (Buffer[BufferOffset]=='\n')
          {
            BufferOffset++;

            if (BufferOffset>=BytesInBuffer) GetData();
          }

          LineBuffer[LinePos]=0; // Null Terminate

          if (LineBuffer[0]) // Data To Check ?
          {
            PrintLine(LineBuffer);
          }
          if (LinesOutput>=N_ND->User.CallData.LinesPerScreen)
          {
            ScreenPausePrompt();
          }
          if (BytesInBuffer==0) Done=TRUE;
        }
      }
      Close(FH);
    }
    else
    {
      UnLock(FL);
      ErrorOpening();
    }
  }
  else
  ErrorOpening();

  DOOR_WriteText(ANSI_RESET "\r\n");
}

void NewFileList( void )
{
  int Days;
  struct Node *node;

  if (FL_PARAM)
  {
    if (sscanf(FL_PARAM,"%d",&Days)<=0) // specified amount of days
    {
      if (!stricmp(FL_PARAM,"S")) // since last call
      {
        Days=10; // *C* work out amount of days since user last called...
                 // *C* add function to mainlibrary to do this!
      }
      else
      if (!stricmp(FL_PARAM,"T")) // todays files
      {
        Days=1;
      }
      else
      {
        DOOR_WriteText("Invalid Option!\r\n");
        return;
      }
    }
    else
    {
      Days=abs(Days); // remove - sign if present...
    }
  }

  if (N_ND->CurrentConf)
  {
    if (N_ND->CurrentConf->FileLists>0)
    {
      node=GetNode(N_ND->CurrentConf->FileList,N_ND->CurrentConf->FileLists-1);
      // *C* remove..
      sprintf(tmpstr,"Displaying Files in %s From %d days ago..\r\n",node->ln_Name,Days);
      DOOR_WriteText(tmpstr);

      FileList(DIR_FORWARDS,node->ln_Name,Days,0);
    }
  }
}

void ReverseFileList( void )
{
  DOOR_WriteText("Look, how any times do I have to tell you that I've not bloody well\r\n"
                 "programmed this mode yet!!!!\r\n");
}

void DoorMain(int argc,char *argv[])
{
  int loop;

  // Put the options in the right place
  for(loop=2;loop<argc;loop++) // if there are any parameters then display them
  {
    switch(loop)
    {
      case 2:
        FL_PARAM=DupStr(argv[loop]);
        break;
      case 3:
        FL_LIST=DupStr(argv[loop]);
        break;
    }
  }

  if (iposition("NEW",N_ND->ActiveDoor->SystemOptions)>=0)
  {
    NewFileList();
  }
  else
  if (iposition("REVERSE",N_ND->ActiveDoor->SystemOptions)>=0)
  {
    ReverseFileList();
  }
  else
  {
    DOOR_WriteText("\r\nErk! Unknown FileLister Mode Selected!\r\n\r\n");
  }

  FreeStr(FL_PARAM);
  FreeStr(FL_LIST);
}

int main(int argc,char *argv[])
{
  if (sscanf(argv[1],"%d",&N_NodeNum)==0)
  {
    printf("Invalid/No Paramaters for door!\n");
    exit (20);
  }
  init("FileLister");

  if (BBSGlobal=HBBS_GimmeBBS())
  {
    if (N_ND=HBBS_NodeDataPtr(N_NodeNum)) // this should not fail in normal circumstances..
    {
      DoorMain(argc,argv);
    }
  }
  cleanup(0);
}
