#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include <dos.h>
#include <exec/types.h>
#include <libraries/dosextens.h>

#include <dlg/dlg.h>
#include <dlg/user.h>
#include <dlg/misc.h>
#include <dlg/input.h>
#include <dlg/menu.h>
#include <dlg/resman.h>
#include <dlg/log.h>

#include <link/io.h>
#include <link/util.h>

#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/dlg.h>

#include <pragmas/dlg.h>

#include <private/Version.h>
#define  ObjRev "1"
const UBYTE version[]="\0$VER: Group " BUILDVER "." ObjRev " ©" COPYRIGHT " by Digerati Dreams "__AMIGADATE__;

void  main(int , char **);
int   HandleBuiltIn(UBYTE);
void  List_Groups(void);
void  Add_Group(void);
void  Delete_Group(void);
void  List_Members(char *);
void  Add_Member(void);
void  Delete_Member(void);
int   Read_Users(void);
void _CXBRK(void);


#define INSTACK RStruct.Command_Stack[0]
#define STK     RStruct.Command_Stack
#define HOT     UserDat.Hot_Keys


struct USER_DATA UserDat;
struct Ram_File  RStruct;
struct Group_Def Group;
struct UserInfo  ui      = {&UserDat, &RStruct};
char             Ext[4];

struct NewShortMenu Menu[8]={{"Abort",1},
                             {"GROUP_Add",1},
                             {"GROUP_AddUser",1},
                             {"GROUP_Del",1},
                             {"GROUP_DelUser",1},
                             {"GROUP_Exit",1},
                             {"GROUP_List",1},
                             {"GROUP_ListUsers",1}
                            };

int   NumElem      =   20;
int   elementnum   =    0;
char *temparray    =  NULL;

char  Overlay      =  FALSE;
char  exitflag     =  FALSE;
char  MenuName[13] = "GROUP_Main";

int                NumUsers =  0;
struct NameStruct *users    =  NULL;


BPTR               sout;
struct Library    *DLGBase = NULL;
struct LangStruct *ls;
char             **SA;


void main(int argc,char **argv)

{char *s;
 char *stack = NULL;

 sout = Output();
 if (!(DLGBase = OpenLibrary(DLGNAME, DLGVERSION)))  exit(5);

 while(--argc > 0)
      {s = *++argv;
       if (*s++=='-')
          {while(*s)
                {switch(toupper(*s))
                       {case 'O':  Overlay = TRUE;
                                   break;

                        case 'S':  if (!--argc)  break;
                                   stack = *++argv;
                                   break;

                        case 'M':  if (!--argc)  break;
                                   strncpy(MenuName,*++argv,12);
                                   MenuName[12] = 0;
                                   break;
                       }
                 s++;
                }
          }
      }


 if (GetDevName(Ext) == -1)   _CXBRK();
 if (!(ls = GetLang(Ext)))    _CXBRK();
 SA = ls->strings;

 if (!ReadUser(&RStruct,&UserDat,Ext))  _CXBRK();
 if (stack)                             InsertStack(STK, stack);

 WriteLog(SYSOP_CONFIG,RStruct.Name,Ext,SA[890]);

 if (!(NumUsers = Read_Users()))
    {AFPrintf(&UserDat, sout, SA[891]);
    _CXBRK();
    }

 while(!exitflag)
      {Chk_Abort();

       if (MenuInput(MenuName,Ext,"GROUP",Menu,8,HandleBuiltIn,&UserDat,&RStruct,UserDat.Help_Level,NULL)==MENUNOTFOUND)
          _CXBRK();
      }

 _CXBRK();
}



int HandleBuiltIn(UBYTE cmd) 

{char string[256];
 long zflag;

 switch(cmd)
       {case 0:         /* Abort */
                exitflag = TRUE;
                break;

        case 1:         /* GROUP_Add */
                Add_Group();
                break;

        case 2:         /* GROUP_AddUser */
                Add_Member();
                break;

        case 3:         /* GROUP_Del */
                Delete_Group();
                break;

        case 4:         /* GROUP_DelUser */
                Delete_Member();
                break;

        case 5:         /* GROUP_Exit */
               _CXBRK();
                break;

        case 6:         /* GROUP_List */
                List_Groups();
                break;

        case 7:         /* GROUP_ListUsers */
                List_Groups();
                zflag = DLGInput(temparray,string,(char *)-1,36,elementnum,6, SA[892]);
                AFPrintf(&UserDat, sout, "\n\n");
                if (zflag==-1)  break;
                List_Members(string);
                break;
       }

 return(TRUE);
}


void List_Groups(void)

{int fp;

 if ((fp=open("DLGConfig:Group/Group.bbs",O_RDONLY))!=EOF)
    {if (!INSTACK)
        {AFPrintf(&UserDat, sout, SA[893]);
         Draw_Line(UserDat.Screen_Width);
        }

     elementnum = 0;
     while(read(fp, &Group, sizeof(Group)) == sizeof(Group))
          {AFPrintf(&UserDat, sout, SA[894],Group.name,Group.gop);
           elementnum = BuildArray(&temparray, Group.name, 36, elementnum, NumElem);
          }
     close(fp);
     BuildArray(&temparray, NULL, 36, elementnum, NumElem);
     NumElem = ((elementnum / NumElem)+1) * NumElem;

     if (!INSTACK)
        {Draw_Line(UserDat.Screen_Width);
         AFPrintf(&UserDat, sout, "\n");
        }
    }

 return;
}


void Add_Group(void)

{long zflag;
 char filename[80];

 zflag = DLGInput(NULL,Group.name,NULL,36,255,3, SA[895]);
 AFPrintf(&UserDat, sout, "\n\n");
 if (!zflag)
    {AFPrintf(&UserDat, sout, SA[896]);
     return;
    }

 ASPrintf(NULL, filename, "DLGConfig:Group/%s.Group", Group.name);
 if (!GetStruct("DLGConfig:Group/Group.bbs", (char *)&Group, sizeof(Group), 36))
    {AFPrintf(&UserDat, sout, SA[897]);
     return;
    }

 for(;;)
    {
     zflag = DLGInput((char *)users,Group.gop,(char *)-1,36,NumUsers,6, SA[898]);
     AFPrintf(&UserDat, sout, "\n\n");
     if (zflag==-1)
        {AFPrintf(&UserDat, sout, SA[899], Group.gop);
         continue;
        }

     break;
    }

 zflag = BoolQuery(SA[900], 1, &ui);
 AFPrintf(&UserDat, sout, "\n\n");
 if (zflag)
    {Capitalize(Group.gop);

     if (AddStruct("DLGConfig:Group/Group.bbs",(char *)&Group,sizeof(Group),36)==-1)
        {AFPrintf(&UserDat, sout, SA[901]);
         return;
        }

     if (AddStruct(filename, Group.gop, 36, 36)==-1)
        {AFPrintf(&UserDat, sout, SA[902]);
         DeleteStruct("DLGConfig:Group/Group.bbs",(char *)&Group,sizeof(Group),36);
         return;
        }

     AFPrintf(&UserDat, sout, SA[903]);
    }

 return;
}

  
void Delete_Group(void)

{char filename[80];
 long zflag;

 List_Groups();
 zflag = DLGInput(temparray,Group.name,(char *)-1,36,elementnum,6, SA[904]);
 AFPrintf(&UserDat, sout, "\n\n");
 if (zflag==-1)
    {AFPrintf(&UserDat, sout, SA[896]);
     return;
    }

 if (DeleteStruct("DLGConfig:Group/Group.bbs",(char *)&Group,sizeof(Group),36)==-1)
    {AFPrintf(&UserDat, sout, SA[905]);
     return;
    }

 ASPrintf(NULL, filename, "DLGConfig:Group/%s.Group", Group.name);
 DeleteFile(filename);
 AFPrintf(&UserDat, sout, SA[906]);
 return;
}


void List_Members(char *name)

{char username[37];
 BPTR gr;

 if (!(gr = OpenGroup(name)))   return;
 AFPrintf(&UserDat, sout, SA[907],name);

 while(NextInGroup(gr, username))
      {if (ReadChar(0) == 3)
          {AFPrintf(&UserDat, sout, SA[908]);
           break;
          }

       AFPrintf(&UserDat, sout, SA[909],username);
      }

 CloseGroup(gr);
 AFPrintf(&UserDat, sout, SA[910]);
 return;
}


void Add_Member(void)

{char name    [37];
 char filename[80];
 long zflag;

 List_Groups();
 zflag = DLGInput(temparray,Group.name,(char *)-1,36,elementnum,6, SA[911]);
 AFPrintf(&UserDat, sout, "\n\n");
 if (zflag==-1)
    {AFPrintf(&UserDat, sout, SA[912]);
     return;
    }

 ASPrintf(NULL, filename, "DLGConfig:Group/%s.Group", Group.name);
 if (GetStruct("DLGConfig:Group/Group.bbs", (char *)&Group, sizeof(Group), 36))
    {AFPrintf(&UserDat, sout, SA[913]);
     return;
    }

 for(;;)
    {
     zflag = DLGInput((char *)users,name,(char *)-1,36,NumUsers,6, SA[914]);
     if (zflag==-1)
        {AFPrintf(&UserDat, sout, "\n\n");
         return;
        }

//     Upper(name);
     Capitalize(name);

     AFPrintf(&UserDat, sout, SA[915]);
     if (AddStruct(filename, name, 36, 36)==-1)
         AFPrintf(&UserDat, sout, SA[916]);
       else
         AFPrintf(&UserDat, sout, SA[917]);
    }

 return;
}


void Delete_Member(void)

{char name[37];
 char filename[80];
 long zflag;

 List_Groups();
 zflag = DLGInput(temparray,Group.name,(char *)-1,36,elementnum,6, SA[911]);
 AFPrintf(&UserDat, sout, "\n\n");
 if (zflag==-1)
    {AFPrintf(&UserDat, sout, SA[912]);
     return;
    }

 ASPrintf(NULL, filename, "DLGConfig:Group/%s.Group", Group.name);
 if (GetStruct("DLGConfig:Group/Group.bbs", (char *)&Group, sizeof(Group), 36))
    {AFPrintf(&UserDat, sout, SA[913]);
     return;
    }

 for(;;)
    {
     zflag = DLGInput((char *)users,name,(char *)-1,36,NumUsers,6, SA[914]);
     if (zflag==-1)
        {AFPrintf(&UserDat, sout, "\n\n");
         return;
        }

     Capitalize(name);

     AFPrintf(&UserDat, sout, SA[915]);
     if (DeleteStruct(filename,name,36,36)==-1)
         AFPrintf(&UserDat, sout, SA[916]);
       else
         AFPrintf(&UserDat, sout, SA[918]);
    }

 AFPrintf(&UserDat, sout, "\n");
 return;
}


int Read_Users()

{ULONG  filesize;

 if (FileSize("DLGConfig:Misc/Users.bbs",&filesize)==-1)  return(FALSE);
 if (!(users = malloc(filesize)))                         return(FALSE);

 GetFirstStruct("DLGConfig:Misc/Users.bbs", (char *)users, filesize);
 return((int)(filesize/(long)sizeof(struct NameStruct)));
}


void _CXBRK(void)

{WriteRam(&RStruct, Ext);

 if (temparray)  free(temparray);
 if (users)      free(users);

 if (!Overlay) ChainProgram("DLG:Menu", Ext);
 CloseLibrary(DLGBase);
 exit(0);
}
