/*

  AskConf
  -------

  Asks the user wether the file is for the current conference or a different one

  options
  =======

    argv[x]
    -------

    2 - filename

    systemoptions
    -------------

    if REMOVEFLAG is present it'll remove the ALL flag in t:

    (so this door is called before CHECKFILES is called to remove the flag..)

  returns
  -------

  X       where X is a conference number, first conference starting at 1



*/

#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>
#include <HBBS/release.h>
char *versionstr="$VER: ConfirmUL "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[1024]; // temp string for displaying text..

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);
}

struct CData
{
  struct List *Confs;
  V_BIGNUM Seen;
  V_BIGNUM Allowed;
};

struct CNode
{
  struct Node node;
  V_BOOL See;
  V_BIGNUM Number;
  V_BOOL Allowed;
};

void DisplayConfList( struct CData *CD)
{
  struct CNode *cn;
  short side=1;
  char numstr[3];

  for (cn=(struct CNode *)CD->Confs->lh_Head;cn->node.ln_Succ;cn=(struct CNode *)cn->node.ln_Succ)
  {
    if (HBBS_AllowConfAccess(cn->Number,NULL) && cn->See)
    {
      if (BBSGlobal->Conferences<10)
      {
        sprintf(numstr,"%ld",cn->Number);
      }
      else
      {
        sprintf(numstr,"%2ld",cn->Number);
      }
      sprintf(outstr,ANSI_BOLD ANSI_FG_PURPLE" ["ANSI_FG_WHITE"%s"ANSI_FG_PURPLE"]"ANSI_RESET ANSI_FG_CYAN" - "ANSI_FG_WHITE"%-25s",numstr,cn->node.ln_Name);
      side++;
      if (side==1 && (cn->Number<BBSGlobal->Conferences))
      {
        strcat(outstr,ANSI_FG_YELLOW " -");
      }
      if (side==3)
      {
        strcat(outstr,"\r\n" ANSI_RESET);
        side=1;
      }
      DOOR_WriteText(outstr);
    }
  }
  if (side==2)
  {
    DOOR_WriteText("\r\n");
  }
  DOOR_WriteText("\r\n");
}

V_BIGNUM PickConference( void )
{
  struct CData CD;

  struct CNode *cn=NULL;
  struct ConfData *cd;
  struct BoolNode *boolnode;
  V_BIGNUM loop;
  V_BIGNUM newconf=0;

  // first we create a list containing the numbers and names of the conferences
  // that the user is allowed to join.
  CD.Seen=0;
  CD.Allowed=0;

  if (CD.Confs=HBBS_CreateList())
  {
    for (loop=0;loop<BBSGlobal->Conferences;loop++) // loop starts at 0!
    {
      cd=(struct ConfData *)GetNode(BBSGlobal->ConfList,loop);
      boolnode=(struct BoolNode *)GetNode(N_ND->User->ConfAcs.See,loop);

      if (cn=(struct CNode *)HBBS_CreateNode(cd->node.ln_Name,sizeof(struct CNode)))
      {
        if (cn->Allowed=HBBS_AllowConfAccess(loop+1,NULL)) CD.Allowed++;
        cn->See=boolnode->Boolean;
        if (HBBS_AllowConfAccess(loop+1,NULL)) CD.Seen++;
        cn->Number=loop+1;
        AddTail(CD.Confs,(struct Node *)cn);
      }
      else
      {
        loop=BBSGlobal->Conferences; // to end loop as we are out of mem!
      }
    }
    if (HBBS_NodesInList(CD.Confs)==BBSGlobal->Conferences)
    {
      // OK, list is now created so we wanna display them to the user..

      if (CD.Seen==0)
      {
        DOOR_WriteText("You have no conferences to choose from!\r\n");
      }
      else
      {
        do
        {
          DOOR_WriteText(ANSI_RESET "Please select a new conference for the file:\r\n\r\n");
          DisplayConfList(&CD);

          DOOR_MenuPrompt("Conference [#] > ",' ');
          strcpy(N_ND->CharsAllowed,"0123456789");

          // hehe, this next bit is cool.. you get sortof hotkeys :-)
          // if your bbs has 20 confs you will be able to enter 2 chars...
          // if it has les than 10 you enter one char. etc...

          sprintf(outstr,"%d",BBSGlobal->Conferences);                                                       //MAXLEN       timeout
          DOOR_GetLine(GL_CVTUPPER|GL_NORETURN|GL_DISPLAY|GL_EDIT|GL_USECHARS|GL_IMMEDIATE|GL_COUNTDOWN,'\0',strlen(outstr),10,NULL);
          if (N_ND->OnlineStatus==OS_ONLINE)
          {
            switch (N_ND->CurrentLine[0])
            {
              case '\0':
                newconf=N_ND->CurrentConf->ConfNum;
                break;
              default:
                sscanf(N_ND->CurrentLine,"%ld",&newconf);
                break;
            }
            DOOR_WriteText("\r\n");
          }
        }
        while (N_ND->OnlineStatus==OS_ONLINE && (!(newconf>=1 && newconf<=BBSGlobal->Conferences)));
      }
    }
    else DOOR_WriteText("Out Of Memory!\r\n");
    FreeStrList(CD.Confs);
  }
  return(newconf);
}

void CreateFlagFile(V_BIGNUM ConfNum,char *FlagFileName)
{
  struct List *FlagFileData;
  if (FlagFileData = HBBS_CreateList())
  {
    sprintf(outstr,"%d",ConfNum);
    if (ERR_NO_ERROR == NewStrNode(outstr,FlagFileData))
    {
      HBBS_SaveFile(FlagFileName,FlagFileData);
    }
    FreeStrList(FlagFileData);
  }
}

void DoorMain(int argc,char *argv[])
{
  struct List *FlagFileData;
  V_BIGNUM confnum = 0;
  V_BOOL multiplefiles = FALSE;
  char FlagFileName[BIG_STR];
  V_BOOL RemoveFlag=TRUE;
  char *MSG_AllForThisConf, 
       *MSG_ForThisConf,
       *MSG_RemainingFiles,
       *MSG_UsingConf;
  struct CfgFileData *Cfg;
  char *filename;
  
  char msg[BIG_STR];                           
  
  MSG_AllForThisConf = DupStr(ANSI_RESET ANSI_FG_CYAN"Are all files for the "ANSI_FG_YELLOW"@C@"ANSI_FG_CYAN" conference ");
  MSG_ForThisConf = DupStr(ANSI_RESET ANSI_FG_CYAN"Is \""ANSI_FG_YELLOW"@F@\""ANSI_FG_CYAN" for the "ANSI_FG_YELLOW"@C@"ANSI_FG_CYAN" conference ");
  MSG_RemainingFiles = DupStr(ANSI_RESET ANSI_FG_CYAN"Use the "ANSI_FG_YELLOW"@C@"ANSI_FG_CYAN" conference for remaining files ");
  MSG_UsingConf = DupStr(ANSI_RESET ANSI_FG_CYAN"Using the "ANSI_FG_WHITE"\""ANSI_FG_YELLOW"@C@"ANSI_FG_WHITE"\""ANSI_FG_CYAN" conference for \""ANSI_FG_YELLOW"@F@"ANSI_FG_CYAN"\"");
  
  if (Cfg = HBBS_LoadConfig("Progdir:AskConf.CFG",LCFG_NOSTRIPCOMMENTS | LCFG_NOSTRIPSPACES))
  {
    HBBS_GetSetting(Cfg,(void *)&MSG_AllForThisConf,VTYPE_STRING,"AllForThisConf",OPT_SINGLE);
    HBBS_GetSetting(Cfg,(void *)&MSG_ForThisConf,VTYPE_STRING,"ForThisConf",OPT_SINGLE);
    HBBS_GetSetting(Cfg,(void *)&MSG_RemainingFiles,VTYPE_STRING,"RemainingFiles",OPT_SINGLE);
    HBBS_GetSetting(Cfg,(void *)&MSG_UsingConf,VTYPE_STRING,"UsingConf",OPT_SINGLE);
    HBBS_FlushConfig(Cfg);
  }                                                                                     
  
  sprintf(FlagFileName,"T:HBBS/AskConf_%d",N_ND->NodeNum);
  
  // if this file exists more than one file is to be checked..

  sprintf(outstr,"T:HBBS/MultipleFiles_%d",N_ND->NodeNum);
  multiplefiles = PathOK(outstr);

  if (iposition("REMOVEFLAG",N_ND->ActiveDoor->SystemOptions)>=0)
  {
    if (UserAround && multiplefiles)
    {
      replace(msg,MSG_AllForThisConf,"@C@",HBBS_ListName(BBSGlobal->ConfList,N_ND->CurrentConf->ConfNum-1));
      
      if (DOOR_AContinuePrompt(msg,DCP_ADDYN|DEFAULT_NO|DCP_NOOLM,5))
      {
        CreateFlagFile(N_ND->CurrentConf->ConfNum,FlagFileName);
        RemoveFlag=FALSE;
      }
    }

    if (RemoveFlag) DeleteFile(FlagFileName);
  }
  else
  {
    
    filename = argv[2];

    // if the user selected the ALL option the conf number to store the rest of the
    // files in is stored in a file which we load here

    if (FlagFileData = HBBS_LoadFile( FlagFileName ))
    {
      confnum = atoi(FlagFileData->lh_Head->ln_Name);
      FreeStrList(FlagFileData);
      FlagFileData=NULL; // *C* unused assignment ?
    } 
                    
    // if the user is on-line and the user has not selected ALL then ask if the file
    // is for this conference

    if (UserAround)
    {
      if (confnum == 0)
      {
        confnum = N_ND->CurrentConf->ConfNum;
        replace(msg,MSG_ForThisConf,"@C@",HBBS_ListName(BBSGlobal->ConfList,confnum-1));
        replace(msg,msg,"@F@",filename);
        
        // use the ! for opposite default. (i.e. default is yes..)
        if (! DOOR_AContinuePrompt(msg,DCP_ADDYN|DEFAULT_YES|DCP_COUNTDOWN|DCP_NOOLM,3))
        {
          confnum = PickConference();
        }


        if (( N_ND->OnlineStatus==OS_ONLINE) && (multiplefiles))
        {
          replace(msg,MSG_RemainingFiles,"@C@",HBBS_ListName(BBSGlobal->ConfList,confnum-1));
          
          if (DOOR_AContinuePrompt(msg,DCP_ADDYN|DEFAULT_NO|DCP_COUNTDOWN|DCP_NOOLM,3))
          {            
            CreateFlagFile(confnum,FlagFileName);
          }
        }
      }
      else
      { 
        replace(msg,MSG_UsingConf,"@C@",HBBS_ListName(BBSGlobal->ConfList,confnum-1));
        replace(msg,msg,"@F@",filename);
        strcat(msg,"\r\n");
        DOOR_WriteText(msg);
      }
    }

    sprintf(outstr,"%d",confnum);
    DOOR_Return(outstr);
  }
}

int main(int argc,char *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("AskConf");

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