/*

  todo:

  put max password and username attempts in config file.
  put min/max username/password lengths in config file.

  function of newuser door

  - Check
    - new users are allowed
    - min new user connect speed
    - ask for NUP
  - Create and initialise a UserData structure
  - Display GuestLogon screen
  - Ask user certain questions and fill UserData structure accordingly
    - make sure that if handle and realname are in use then check all other
      accounts to see if someone else has the same realname or handle as
      the new user.
  - Ask user if they are sure they want a new account
  - Add new UserData structure to the user database making sure that
    the STATUS variable in the UserData structure is set to 'N'
  - return USERADDED if user added ok, otherwise return FAILED

*/


#include <exec/types.h>
#include <exec/memory.h>
#include <clib/exec_protos.h>
#include <clib/alib_protos.h>

#include <dos/dos.h>
#include <clib/dos_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/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/ANSI_Codes.h>

ULONG __stack=20000;

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

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

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


/********************************* ACTUAL DOOR CODE **************************/

BOOL GetOption(char *prompt,char *destination,short minlen, short maxlen, BOOL required)
{
  // returns FALSE for carrier loss, or true when done
  BOOL Done=FALSE;
  while (N_ND->OnlineStatus==OS_ONLINE && !Done)
  {
    DOOR_WriteText(ANSI_RESET ANSI_FG_YELLOW);
    DOOR_WriteText(prompt);
    DOOR_WriteText(ANSI_FG_BLUE " : " ANSI_FG_WHITE);
    if (DOOR_GetLine(GL_EDIT|GL_DISPLAY|GL_HISTORY,'\0',maxlen,0,NULL)==IN_GOTLINE)
    {
      if (strlen(N_ND->CurrentLine)>=minlen && strlen(N_ND->CurrentLine)<=maxlen)
      {
        strcpy(destination,N_ND->CurrentLine);
        Done=TRUE;
      }
      if (!required && N_ND->CurrentLine[0]==0) Done=TRUE;
    }
  }
  return(Done);
}

void DoorMain( int argc,char *argv[] )
{
  BOOL Done=FALSE;
  BOOL UserAdded=FALSE;
  short loop;
  char tmpstr[BIG_STR];

  // initialise UserData structure for our new user.

  HBBS_InitUserData(&N_ND->User.CallData);

  // Get the users handle from the parameters passed to the door, remembering
  // that the users handle MAY have spaces in it..

  N_ND->User.CallData.Handle[0]=0;
  for (loop=2;loop<argc;loop++)
  {
    if (loop!=2) strcat(N_ND->User.CallData.Handle," ");
    strcat(N_ND->User.CallData.Handle,argv[loop]);
  }

  // Ok, we need to see if new users are allowed
  // a) at this time
  // b) on this node

  // *C* add time check..

  if (N_ND->NodeSettings.AllowNewUsers==FALSE)
  {
    DOOR_DisplaySpecialScreen(SSCREEN_NONEWAT_ALL);
  }
  else
  {
    // display the screen "NoNewAt_ThisTime" if user is not allowed at this time.

    // display the screen "NoNewAt_BAUD" if users modem is too slow..

    sprintf(tmpstr,"NoNewAt_%s",N_ND->ConnectBaud);
    if (DOOR_DisplaySpecialScreen(tmpstr))
    {
      DOOR_HangUp();
      N_ND->OnlineStatus=OS_OFFLINE;
    }
    else
    {

      while (N_ND->OnlineStatus==OS_ONLINE && !Done)
      {
        DOOR_DisplaySpecialScreen("GuestLogin");
        sprintf(tmpstr,ANSI_RESET ANSI_CLS ANSI_FG_CYAN "You now need to enter a password to use on this system, make sure it is at\r\n"
                       "least %d character%s long, preferably with some numbers in it somewhere\r\n",BBSGlobal->MinPasswordLength,BBSGlobal->MinPasswordLength == 1 ? "" : "s");
        DOOR_WriteText(tmpstr);
        if (GetOption("Password To Use",N_ND->User.CallData.Password,BBSGlobal->MinPasswordLength,LEN_PASSWORD,TRUE))
        {
          DOOR_WriteText(ANSI_FG_CYAN"Please Enter Your Real Name\r\n");
          if (GetOption("Real Name",N_ND->User.CallData.RealName,3,LEN_REALNAME,FALSE))
          {
            DOOR_WriteText(ANSI_FG_CYAN "If you are in any scene groups, then enter the name of them now\r\n"
                           "(Note: This is used by WHO doors and bulletins to display a bit of\r\n"
                           "Information about you)\r\n");
            if (GetOption("Scene Group",N_ND->User.CallData.Group,2,LEN_GROUP,FALSE))
            {
              DOOR_WriteText(ANSI_FG_CYAN "Enter the name of the town/city you are calling from\r\n");
              if (GetOption("City",N_ND->User.CallData.GeoLocation,3,LEN_GEOLOCATION,FALSE))
              {
                DOOR_WriteText(ANSI_FG_CYAN "Enter The Country you are calling from\r\n");
                if (GetOption("Country",N_ND->User.CallData.Country,2,LEN_COUNTRY,FALSE))
                {
                  DOOR_WriteText(ANSI_FG_CYAN "Please enter your voice phone number\r\n");
                  if (GetOption("Phone Number",N_ND->User.CallData.PhoneNumber,5,LEN_PHONENUMBER,FALSE))
                  {
                    DOOR_WriteText(ANSI_FG_CYAN "Please enter details of all your computers\r\n");
                    if (GetOption("Computer Type",N_ND->User.CallData.ComputerType,2,LEN_COMPUTERTYPE,FALSE))
                    {
                      DOOR_WriteText(ANSI_FG_YELLOW"\r\nThankyou!\r\n");

                      if (HBBS_AddUser(&N_ND->User.CallData))
                      {
                        memcpy(&N_ND->User.NormalData,&N_ND->User.CallData,sizeof(struct UserData));
                        N_ND->User.Valid=TRUE;

                        DOOR_SystemDoor("SelectLanguage",NULL);
                        if (N_ND->OnlineStatus==OS_ONLINE)
                        {
                          DOOR_SystemDoor("LinesPerScreen",NULL);
                          if (N_ND->OnlineStatus==OS_ONLINE)
                          {
                            HBBS_SaveUserData(&N_ND->User.CallData);
                            DOOR_DisplaySpecialScreen("Joined");
                            N_ND->Actions[ACTN_NEWUSER]=ACTC_NEWUSER;
                            UserAdded=TRUE;
                            Done=TRUE;
                          }
                          else
                          {
                            DOOR_WriteText("Failed to add user\r\n");
                            HBBS_LogError(BBSGlobal->ErrorLogFile,ERR_GENERAL,"Failed To Create A NewUser Account",TYPE_WARNING);
                          }//||
                        } // ||
                      }  //  ||
                    }   //   ||
                  }    //    ||
                }     //     ||
              }      //      ||
            }       //       ||
          }        //        ||     pretty :-)
        }         //         ||
      }          //          ||
    }           //           ||
  }            //            ||

  DOOR_Return(UserAdded ? "USERADDED" : "FAILED");
  DOOR_Continue(FALSE);
}

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

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