/* **** HBBS Door Code****************************************************** */

/*
  DoorName
  ========

    what the door does

  Version
  =======

    x.xx, release xx, dd/mm/yyyy

  Options
  =======

    N_ND->ActiveDoor->SystemOptions
    -------------------------------



    Command Line Arguments
    ----------------------

    2  <option>

    3  ...

    4  .

  ToDo
  ====

    what you still have to do



*/

/* **** Includes *********************************************************** */

#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>

#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: AccountEdit "RELEASE_STR;

/* **** Variables ********************************************************** */

/* Common */

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

struct BBSGlobalData *BBSGlobal = NULL;
struct NodeData *N_ND           = NULL;
int    N_NodeNum                = -1;
char   outstr[1024];

long __stack=16*1024; // increse this in 4k incrments if you suffer from
                      // random/suprious crashings after or during the running
                      // of your door.

int    gargc;         // these are just copies of main()'s argc and argv..
char   **gargv;

/* Used By This Door Only */

BOOL SysopMode=FALSE;
BOOL CallDataOnly=TRUE;
ULONG GLFlags=GL_EDIT + GL_DISPLAY;



/* **** Functions ********************************************************** */


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

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

/* **** DoorMain *********************************************************** */

LONG EditUser ( struct UserData *UserDataPtr,LONG EUFlags)
{
  // Return Values

  #define EU_Save 1
  #define EU_Cancel 0

  // Flags

  #define EUF_None 0


  V_BIGNUM BigNum,OptionNum;
  V_SMALLNUM SmallNum;
  BOOL Done=FALSE;
  LONG Retval=EU_Cancel;
  struct UserData User;

  CopyMem(UserDataPtr,&User,sizeof(struct UserData));

  do
  {
    DOOR_WriteText(ANSI_RESET ANSI_CLS);

    strNcpy(outstr,gargv[0],(PathPart(gargv[0])-gargv[0])+1);
    strcat(outstr,"AccountEdit.SCR");
    DOOR_DisplayScreen(outstr);

    sprintf(outstr," 1) Handle         :\"%s\"\r\n",User.Handle);
    DOOR_WriteText(outstr);
    sprintf(outstr," 2) Password       :\"%s\"\r\n",User.Password);
    DOOR_WriteText(outstr);
    sprintf(outstr," 3) Status         :\"%c\"\r\n",User.Status);
    DOOR_WriteText(outstr);
    sprintf(outstr," 4) Group          :\"%s\"\r\n",User.Group);
    DOOR_WriteText(outstr);
    sprintf(outstr," 5) Access Level   :\"%d\"\r\n",User.Access);
    DOOR_WriteText(outstr);
    sprintf(outstr," 6) Bytes Ratio    :\"%d\"\r\n",User.BytesRatio);
    DOOR_WriteText(outstr);
    sprintf(outstr," 7) Files Ratio    :\"%d\"\r\n",User.FilesRatio);
    DOOR_WriteText(outstr);
    sprintf(outstr," 8) Bytes Upload   :\"%d\"\r\n",User.UploadBytes);
    DOOR_WriteText(outstr);
    sprintf(outstr," 9) Files Upload   :\"%d\"\r\n",User.UploadFiles);
    DOOR_WriteText(outstr);
    sprintf(outstr,"10) ConfAcs File   :\"%s\"\r\n",User.ConfAcsDataFile);
    DOOR_WriteText(outstr);
    sprintf(outstr,"11) SentBy         :\"%s\"\r\n",User.SentBy);
    DOOR_WriteText(outstr);
    sprintf(outstr,"12) Time Allowed   :\"%d\"\r\n",User.TimeAllowed);
    DOOR_WriteText(outstr);
    sprintf(outstr,"13) Time Used      :\"%d\"\r\n",User.TimeUsed);
    DOOR_WriteText(outstr);
    sprintf(outstr,"14) Extra Time     :\"%d\"\r\n",User.ExtraTimeLimit);
    DOOR_WriteText(outstr);
    sprintf(outstr,"15) Preferred Conf :\"%d\"\r\n",User.PreferedConf);
    DOOR_WriteText(outstr);
    sprintf(outstr,"16) Last Conf      :\"%d\"\r\n",User.LastConf);
    DOOR_WriteText(outstr);

    DOOR_MenuPrompt("\r\n[S]ave, [C]ancel, [H]elp, [V]alidate or # of option >",0);
    if (DOOR_GetLine(GLFlags,'\0',0,0,NULL)==IN_GOTLINE)
    {
      RemoveSpaces(N_ND->CurrentLine);
      if (stricmp("S",N_ND->CurrentLine)==0)
      {
        DOOR_WriteText("Save\r\n");
        Retval=EU_Save;
        Done=TRUE;
      }
      else
      if (stricmp("C",N_ND->CurrentLine)==0)
      {
        DOOR_WriteText("Cancel\r\n");
        Done=TRUE;
      }
      else
      if (stricmp("H",N_ND->CurrentLine)==0)
      {
        DOOR_WriteText("To use the Validate option, just set the access level for the user\r\n"
                       "Then use the V option and the rest of the users settings will be changed\r\n");
        DOOR_PausePrompt(NULL);
      }
      else
      if (stricmp("V",N_ND->CurrentLine)==0)
      {
        // Set VALIDATED status
        User.Status=USER_VALIDATED;

        sprintf(outstr,"%d",User.Access);
        if ((BigNum=HBBS_FindNodeNum(BBSGlobal->AcsLevelList,outstr))>=0)
        {
          strcpy(User.ConfAcsDataFile,HBBS_ListName(BBSGlobal->AcsLevelConfAcsDef,BigNum));
        }
      }
      else
      {
        DOOR_WriteText("\r\n");
        OptionNum=0;
        if (sscanf(N_ND->CurrentLine,"%d",&OptionNum))
        {
          switch (OptionNum)
          {
            case 1: // handle
              DOOR_WriteText("New Handle >");
              DOOR_GetLine(GLFlags,0,LEN_HANDLE,0,User.Handle);
              if (N_ND->CurrentLine[0])
              {
                strcpy(User.Handle,N_ND->CurrentLine);
              }
              break;
            case 2: // Password
              DOOR_WriteText("New Password >");
              DOOR_GetLine(GLFlags,0,0,0,User.Password);
              if (N_ND->CurrentLine[0])
              {
                strcpy(User.Password,N_ND->CurrentLine);
              }
              break;
            case 3: //status
              sprintf(outstr,"%c",User.Status);
              DOOR_WriteText("New Status >");
              DOOR_GetLine(GLFlags,0,1,0,outstr);
              if (N_ND->CurrentLine[0])
              {
                User.Status=N_ND->CurrentLine[0];
              }
              break;
            case 4: // Password
              DOOR_WriteText("New Group >");
              DOOR_GetLine(GLFlags,0,LEN_GROUP,0,User.Group);
              if (N_ND->CurrentLine[0])
              {
                strcpy(User.Group,N_ND->CurrentLine);
              }
              break;
            case 5: //access level
              sprintf(outstr,"%ld",User.Access);
              DOOR_WriteText("New Access >");
              DOOR_GetLine(GLFlags,0,0,0,outstr);
              if (sscanf(N_ND->CurrentLine,"%d",&SmallNum))
              {
                // validate access level!
                if (HBBS_FindNodeNum(BBSGlobal->AcsLevelList,N_ND->CurrentLine)!=-1)
                {
                  User.Access=SmallNum;
                }
                else
                {
                  DOOR_PausePrompt("Invalid Access Level, check HBBS:Access/Levels/Level_List for valid ones");
                }
              }
              break;
            case 6: // bytes ratio
              sprintf(outstr,"%ld",User.BytesRatio);
              DOOR_WriteText("New Bytes Ratio >");
              DOOR_GetLine(GLFlags,0,0,0,outstr);
              if (sscanf(N_ND->CurrentLine,"%d",&SmallNum))
              {
                User.BytesRatio=SmallNum;
              }
              break;
            case 7: // files ratio
              DOOR_WriteText("New Files Ratio >");
              sprintf(outstr,"%ld",User.FilesRatio);
              DOOR_GetLine(GLFlags,0,0,0,outstr);
              if (sscanf(N_ND->CurrentLine,"%d",&SmallNum))
              {
                User.FilesRatio=SmallNum;
              }
              break;
            case 8: //bytes uploaded
              DOOR_WriteText("New Bytes Uploaded >");
              sprintf(outstr,"%ld",User.UploadBytes);
              DOOR_GetLine(GLFlags,0,0,0,outstr);
              if (sscanf(N_ND->CurrentLine,"%d",&BigNum))
              {
                User.UploadBytes=BigNum;
              }
              break;
            case 9: //files uploaded
              DOOR_WriteText("New Files Uploaded >");
              sprintf(outstr,"%ld",User.UploadFiles);
              DOOR_GetLine(GLFlags,0,0,0,outstr);
              if (sscanf(N_ND->CurrentLine,"%d",&BigNum))
              {
                User.UploadFiles=BigNum;
              }
              break;
            case 10: // ConfAcs File
              DOOR_WriteText("Access File >");
              DOOR_GetLine(GLFlags,0,LEN_CONFACCESSFILE,0,User.ConfAcsDataFile);
              if (N_ND->CurrentLine[0])
              {
                strcpy(outstr,"HBBS:System/Data/ConfAcs");
                AddPart(outstr,N_ND->CurrentLine,1024);
                strcat(outstr,".CFG");
                if (PathOK(outstr))
                {
                  strcpy(User.ConfAcsDataFile,N_ND->CurrentLine);
                }
              }
              break;
            case 11: // Sentby File
              DOOR_WriteText("SentBy >");
              DOOR_GetLine(GLFlags,0,LEN_SENTBY,0,User.SentBy);
              strcpy(User.SentBy,N_ND->CurrentLine);
              break;
            case 12: // Time Allowed
              DOOR_WriteText("Time Allowed >");
              sprintf(outstr,"%ld",User.TimeAllowed);
              DOOR_GetLine(GLFlags,0,0,0,outstr);
              if (sscanf(N_ND->CurrentLine,"%d",&SmallNum))
              {
                User.TimeAllowed=SmallNum;
              }
              break;
            case 13: // Time Used
              DOOR_WriteText("Time Used >");
              sprintf(outstr,"%ld",User.TimeUsed);
              DOOR_GetLine(GLFlags,0,0,0,outstr);
              if (sscanf(N_ND->CurrentLine,"%d",&SmallNum))
              {
                User.TimeUsed=SmallNum;
              }
              break;
            case 14: // Extra Time Limit
              DOOR_WriteText("Extra Time Limit >");
              sprintf(outstr,"%ld",User.ExtraTimeLimit);
              DOOR_GetLine(GLFlags,0,0,0,outstr);
              if (sscanf(N_ND->CurrentLine,"%d",&SmallNum))
              {
                User.ExtraTimeLimit=SmallNum;
              }
              break;
            case 15: // Preferred Conf
              DOOR_WriteText("Preferred Conf >");
              sprintf(outstr,"%ld",User.PreferedConf);
              DOOR_GetLine(GLFlags,0,0,0,outstr);
              if (sscanf(N_ND->CurrentLine,"%d",&SmallNum))
              {
                User.PreferedConf=SmallNum;
              }
              break;
            case 16: // Last Conf
              DOOR_WriteText("Last Conf >");
              sprintf(outstr,"%ld",User.LastConf);
              DOOR_GetLine(GLFlags,0,0,0,outstr);
              if (sscanf(N_ND->CurrentLine,"%d",&SmallNum))
              {
                User.LastConf=SmallNum;
              }
              break;

            Default :
              DOOR_WriteText("Unknown Option!\r\n");
              break;
          }
        }
      }
    }
    else
    {
      Done=TRUE;
    }
  } while (!Done);

  if (Retval==EU_Save)
  {
    CopyMem(&User,UserDataPtr,sizeof(struct UserData));
  }

  return(Retval);

}
void DoorMain( void )
{
  struct UserData UserDat;
//  struct UserData *User=NULL;
  BOOL Done2,Done=FALSE;

  struct List *UserList;
  struct Node *node,*CurrentUser;
  V_BIGNUM UserID,UsersInList;


  if ((gargc>=3) && (iposition("SYSOPONLY",gargv[2])>=0))
  {
    SysopMode=TRUE;
    CallDataOnly=FALSE;
    DOOR_WriteText(ANSI_RESET ANSI_CLS "Wait while the sysop changes your account settings!\r\n");

    /* Block Output to the serial port so the user doesn't see what we're doing.. */

    N_ND->NodeFlags+=NFLG_BLOCKSERIAL;


    GLFlags+=GL_SYSOP;

    if ((gargc>=4) && (iposition("CALLONLY",gargv[3])>=0))
    {
      CallDataOnly=TRUE;
    }

    if (N_ND->User.Valid)
    {
      if (EditUser(&N_ND->User.CallData,EUF_None)==EU_Save)
      {

        if (!CallDataOnly)
        {
          CopyMem(&N_ND->User.CallData,&N_ND->User.NormalData,sizeof(struct UserData));
        }

        if (SysopMode && CallDataOnly) DOOR_WriteText("Changes only last for this call!\r\n");
      }
    }
    else
    {
      DOOR_SysopText("No User is Logged On Yet!\r\n");
    }
    N_ND->NodeFlags-=NFLG_BLOCKSERIAL;

    HBBS_SetAccess();

  }
  else
  {
    do
    {
      DOOR_WriteText(ANSI_CLS ANSI_RESET ANSI_FG_YELLOW "Account Editor\r\n" ANSI_FG_WHITE);
      strcpy(N_ND->CharsAllowed,"SsNnQq");
      DOOR_MenuPrompt("[N]ew Users, [S]pecific User, [Q]uit >",'Q');
      DOOR_GetLine(GLFlags | GL_IMMEDIATE | GL_USECHARS,0,1,0,NULL);
      if (N_ND->OnlineStatus==OS_ONLINE && N_ND->CurrentLine[0])
      {
        switch(toupper(N_ND->CurrentLine[0]))
        {
          case 'S':
            DOOR_WriteText("Enter Handle :");
            DOOR_GetLine(GLFlags,0,LEN_HANDLE,0,NULL);
            RemoveSpaces(N_ND->CurrentLine);
            if (N_ND->CurrentLine[0])
            {
              if (HBBS_ValidUserHandle(N_ND->CurrentLine,&UserDat))
              {
//                User=&UserDat;

                if (EditUser(&UserDat,EUF_None)==EU_Save)
                {
                  HBBS_SaveUserData(&UserDat);
                }

              }
              else
              {
                DOOR_WriteText("Could Not Find That User!\r\n");
              }
            }
            break;
          case 'N':
            DOOR_WriteText("Searching...");

            /*
              Build linked list of users in memory, just needs to contain userid of user
              this way we can go [N]ext and [P]rev even after you have validated a user
              (the user's status may have been changed so we couldn't search backwards
              from current to find the last userwith a status of N)
            */

            if (UserList=HBBS_CreateList())
            {
              UsersInList=0;
              CurrentUser=0;
              for (UserID=1;UserID<=BBSGlobal->TotalUsers;UserID++)
              {
                if (HBBS_LoadUser(UserID,NULL,NULL,&UserDat) && UserDat.Status==USER_NEW)
                {
                  if (node=HBBS_CreateNode(0,NULL)) // *C* could change NULL to UserDat->Handle..
                  {
                    node->ln_Pri=UserID;
                    AddTail(UserList,node);
                    UsersInList++;
                  }
                }
              }

              sprintf(outstr,"Found %d new user%s  - Press Return",UsersInList,UsersInList==1 ? "" : "s");
              DOOR_PausePrompt(outstr);

              if (UsersInList)
              {
                CurrentUser=UserList->lh_Head;

                Done2=FALSE;

                do
                {
                  if (HBBS_LoadUser(CurrentUser->ln_Pri,NULL,NULL,&UserDat))
                  {
                    sprintf(outstr,ANSI_CLS ANSI_FG_WHITE "Current User: %s / %s \r\n",UserDat.Handle,UserDat.Group);
                    DOOR_WriteText(outstr);
                    DOOR_MenuPrompt("Options: [E]dit, [D]elete, [N]ext, [P]rev, [Q]uit >",'E');
                    strcpy(N_ND->CharsAllowed,"EeDdNnPpQq");
                    DOOR_GetLine(GLFlags | GL_IMMEDIATE | GL_USECHARS,0,1,0,NULL);
                    if (N_ND->OnlineStatus==OS_ONLINE)
                    {
                      switch(toupper(N_ND->CurrentLine[0]))
                      {
                        case 'D':
                          if (DOOR_ContinuePrompt("Are you sure!",DCP_ADDYN))
                          {
                            UserDat.Status=USER_DELETED;
                            HBBS_SaveUserData(&UserDat);
                          }
                          break;
                        case 'P':
                          if ((struct Node **)CurrentUser->ln_Pred != &UserList->lh_Head)
                          {
                            CurrentUser=CurrentUser->ln_Pred;
                          }
                          else DOOR_PausePrompt("No More! - Press Return");
                          break;
                        case 'N':
                          if ((struct Node **)CurrentUser->ln_Succ != &UserList->lh_Tail)
                          {
                            CurrentUser=CurrentUser->ln_Succ;
                          }
                          else DOOR_PausePrompt("No More! - Press Return");
                          break;
                        case 'Q':
                          Done2=TRUE;
                          break;
                        case 'E':
                        default:
                          if (EditUser(&UserDat,EUF_None)==EU_Save)
                          {
                            HBBS_SaveUserData(&UserDat);
                          }
                          break;
                      }

                    } else Done2=TRUE;

                  }
                  else Done2=TRUE;

                } while (!Done2);
                HBBS_FreeListNodes(UserList);
              }
              FreeVec(UserList);
            } else DOOR_WriteText("No Mem\r\n");

            break;
          case 'Q':
            Done=TRUE;
            break;
        }
      }
      if (N_ND->OnlineStatus==OS_OFFLINE) Done=TRUE;
    } while (!Done);
  }

  DOOR_WriteText("Done.\r\n");
}

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);
  }
  init("AccountEdit");

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

/* **** End Of File ******************************************************** */
