#include <CrashTickPrefs.h>

struct Hook GroupsHelpHook = { {NULL}, HelpHookEntry,NULL,(APTR)HELP_GROUPS};

struct List Groups_TempList;
struct List Groups_TempAccessList;

struct TempNode *Groups_CurrentNode;
struct TempNode *Groups_CurrentAccessNode;

uchar *Groups_Nodeflags[5];

extern APTR mempool;

void Groups_MakeAccessLine(struct TempNode *tn)
{
   struct ConfigNode *cnode;
   uchar buf[50];

   cnode=tn->UserData;

   PrintFull4D(&cnode->Node,buf);

   if(CheckFlags('A'+Groups_CurrentNode->num,cnode->FullAccessGroups))
      sprintf(tn->buf,"*%s",buf);

   else if(CheckFlags('A'+Groups_CurrentNode->num,cnode->ReadOnlyGroups))
      sprintf(tn->buf,"!%s",buf);

   else if(CheckFlags('A'+Groups_CurrentNode->num,cnode->WriteOnlyGroups))
      sprintf(tn->buf,"@%s",buf);

   else
      sprintf(tn->buf,"%s",buf);
}

void Groups_SetCurrentAccess(ulong num)
{
   struct TempNode *tn;
   ulong c;
   struct ConfigNode *cnode;

   if(!config.CNodeList.First)
   {
      Groups_CurrentAccessNode=0;
      return;
   }

   tn=(struct TempNode *)Groups_TempAccessList.lh_Head;

   for(c=0;c<num;c++)
      tn=(struct TempNode *)tn->Node.ln_Succ;

   Groups_CurrentAccessNode=tn;

   cnode=tn->UserData;

   if(CheckFlags('A'+Groups_CurrentNode->num,cnode->FullAccessGroups))
      LT_SetAttributes(parthandle,5001,GTCY_Active,1,TAG_END);

   else if(CheckFlags('A'+Groups_CurrentNode->num,cnode->ReadOnlyGroups))
      LT_SetAttributes(parthandle,5001,GTCY_Active,2,TAG_END);

   else if(CheckFlags('A'+Groups_CurrentNode->num,cnode->WriteOnlyGroups))
      LT_SetAttributes(parthandle,5001,GTCY_Active,3,TAG_END);

   else
      LT_SetAttributes(parthandle,5001,GTCY_Active,0,TAG_END);
}

void Groups_SetCurrent(ulong num)
{
/*
   sätt lista
   ghosta om behövs
   aktivera?
*/

   ulong c;
   struct ConfigNode *cnode;
   struct TempNode *tn;

   Groups_CurrentNode=(struct TempNode *)Groups_TempList.lh_Head;

   for(c=0;c<num;c++)
      Groups_CurrentNode=(struct TempNode *)Groups_CurrentNode->Node.ln_Succ;

   LV_SetCurrent(parthandle,4000,&Groups_TempList,Groups_CurrentNode);
   LT_SetAttributes(parthandle,4001,GTST_String,config.cfg_GroupNames[num],TAG_END);

   LT_SetAttributes(parthandle,5000,GTLV_Labels,~0,TAG_END);

   tn=(struct TempNode *)Groups_TempAccessList.lh_Head;
   c=0;

   for(cnode=(struct ConfigNode *)config.CNodeList.First;cnode;cnode=cnode->Next)
   {
      tn->num=c;
      tn->UserData=cnode;
      Groups_MakeAccessLine(tn);
      tn=(struct TempNode *)tn->Node.ln_Succ;
      c++;
   }

   LT_SetAttributes(parthandle,5000,GTLV_Labels,&Groups_TempAccessList,TAG_END);

   LT_SetAttributes(parthandle,4000,GTLV_Selected,num,TAG_END);

   if(config.CNodeList.First)
   {
      LT_SetAttributes(parthandle,5000,GTLV_Selected,0,GTLV_MakeVisible,0,TAG_END);
      Groups_SetCurrentAccess(0);
   }
}

void Groups_UpdateConfig(void)
{
   return;
}

/* 

   types:

   0: no access
   1: full access
   2: read-only

*/

void Groups_SetAccess(ulong type)
{
   uchar destgroup[30];
   ulong c,d;
   struct ConfigNode *cnode;

   cnode=(struct ConfigNode *)Groups_CurrentAccessNode->UserData;

   d=0;

   for(c=0;c<26;c++)
   {
      if(c == Groups_CurrentNode->num)
      {
         if(type == 1)
            destgroup[d++]='A'+c;
      }
      else
      {
         if(CheckFlags('A'+c,cnode->FullAccessGroups))
            destgroup[d++]='A'+c;
      }
   }

   destgroup[d]=0;
   strcpy(cnode->FullAccessGroups,destgroup);

   d=0;

   for(c=0;c<26;c++)
   {
      if(c == Groups_CurrentNode->num)
      {
         if(type == 2)
            destgroup[d++]='A'+c;
      }
      else
      {
         if(CheckFlags('A'+c,cnode->ReadOnlyGroups))
            destgroup[d++]='A'+c;
      }
   }

   destgroup[d]=0;
   strcpy(cnode->ReadOnlyGroups,destgroup);

   d=0;

   for(c=0;c<26;c++)
   {
      if(c == Groups_CurrentNode->num)
      {
         if(type == 3)
            destgroup[d++]='A'+c;
      }
      else
      {
         if(CheckFlags('A'+c,cnode->WriteOnlyGroups))
            destgroup[d++]='A'+c;
      }
   }

   destgroup[d]=0;
   strcpy(cnode->WriteOnlyGroups,destgroup);

   LT_SetAttributes(parthandle,5000,GTLV_Labels,~0,TAG_END);
   Groups_MakeAccessLine(Groups_CurrentAccessNode);
   LT_SetAttributes(parthandle,5000,GTLV_Labels,&Groups_TempAccessList,TAG_END);
   LT_SetAttributes(parthandle,5001,GTCY_Active,type,TAG_END);
   config.configchanged=TRUE;

/*   Printf("%lu, %s, %s\n",type,cnode->FullAccessGroups,cnode->ReadOnlyGroups); */
}

void PartGroups(void)
{
   struct IntuiMessage *IntuiMessage;
   APTR iaddress;
   ULONG class,code,qualifier,nodes;
   struct ConfigNode *cnode;
   struct TempNode *tempnodes,*tempaccessnodes;
   ULONG c;

   Groups_Nodeflags[0]=getString(PREFS_NODEACCESS_NO);
   Groups_Nodeflags[1]=getString(PREFS_NODEACCESS_FULL);
   Groups_Nodeflags[2]=getString(PREFS_NODEACCESS_NOHATCH);
   Groups_Nodeflags[3]=getString(PREFS_NODEACCESS_HATCHONLY);
   Groups_Nodeflags[4]=NULL;

   NewList(&Groups_TempList);
   NewList(&Groups_TempAccessList);

   nodes=0;

   for(cnode=(struct ConfigNode *)config.CNodeList.First;cnode;cnode=cnode->Next)
      nodes++;

   if(nodes == 0)
      nodes=1; /* A work-around, but the easiest way */

   tempnodes=AllocCleared(26*sizeof(struct TempNode));
   tempaccessnodes=AllocCleared(nodes*sizeof(struct TempNode));

   if(!tempnodes || !tempaccessnodes)
   {
      if(tempnodes)        LibFreePooled(mempool,tempnodes,26*sizeof(struct TempNode));
      if(tempaccessnodes)  LibFreePooled(mempool,tempaccessnodes,nodes*sizeof(struct TempNode));
      DisplayBeep(NULL);
      return;
   }

   for(c=0;c<26;c++)
   {
      sprintf(tempnodes[c].buf,"%lc: %s",'A'+c,config.cfg_GroupNames[c]);
      tempnodes[c].UserData=(APTR)FALSE;
      tempnodes[c].num=c;
      tempnodes[c].Node.ln_Name=tempnodes[c].buf;
      AddTail(&Groups_TempList,(struct Node *)&tempnodes[c]);
   }

   for(c=0;c<nodes;c++)
   {
      tempaccessnodes[c].Node.ln_Name=tempaccessnodes[c].buf;
      AddTail(&Groups_TempAccessList,(struct Node *)&tempaccessnodes[c]);
   }

   parthandle = LT_CreateHandleTags(scr,LH_EditHook,     &StrEditHook,
                                        LH_RawKeyFilter, FALSE,
                                        LH_LocaleHook,   &LocaleHook,
                                        TAG_DONE);

   if(!parthandle)
   {
      LibFreePooled(mempool,tempnodes,26*sizeof(struct TempNode));
      LibFreePooled(mempool,tempaccessnodes,nodes*sizeof(struct TempNode));
      return;
   }

   LT_New(parthandle,
      LA_Type,      HORIZONTAL_KIND,
      TAG_DONE);

      LT_New(parthandle,
         LA_Type,      VERTICAL_KIND,
         LA_LabelID,   PREFS_GROUPS_GROUPS,
         TAG_DONE);

         LT_New(parthandle,
            LA_Type,       LISTVIEW_KIND,
            LA_Chars,      20,
            LALV_LockSize, TRUE,
            LALV_Lines,    10,
            LALV_CursorKey,TRUE,
            GTLV_Labels,   &Groups_TempList,
            LALV_Link,     NIL_LINK,
            LA_ID,         4000,
            TAG_DONE);

         LT_New(parthandle,
            LA_Type,      STRING_KIND,
            LA_LabelID,   PREFS_GROUPS_NAME,
            LA_LabelPlace,PLACE_ABOVE,
            LA_ExtraSpace,TRUE,
            GTST_MaxChars,79,
            LA_ID,        4001,
            TAG_DONE);

      LT_EndGroup(parthandle);

      LT_New(parthandle,
         LA_Type,      VERTICAL_KIND,
         LA_LabelID,   PREFS_GROUPS_NODES,
         TAG_DONE);

         LT_New(parthandle,
            LA_Type,       LISTVIEW_KIND,
            LA_Lines,      12,
            LA_Chars,      20,
            LALV_LockSize, TRUE,
            LA_ID,         5000,
            LALV_Link,     NIL_LINK,
            TAG_DONE);

         LT_New(parthandle,
            LA_Type,          CYCLE_KIND,
            LA_ID,            5001,
            GTCY_Labels,      Groups_Nodeflags,
            TAG_DONE);

      LT_EndGroup(parthandle);

   LT_EndGroup(parthandle);

   partwin=LT_Build(parthandle,LAWN_IDCMP,    IDCMP_CLOSEWINDOW|IDCMP_RAWKEY,
                               LAWN_Parent,   mainwin,
                               LAWN_HelpHook, &GroupsHelpHook,
                               LAWN_Title,    getString(PREFS_BUTTON_GROUPS),
                               WA_Flags,      WFLG_ACTIVATE|WFLG_CLOSEGADGET|WFLG_DEPTHGADGET|WFLG_DRAGBAR|WFLG_NEWLOOKMENUS,
                               TAG_END);

   if(!partwin)
   {
      LT_DeleteHandle(parthandle);
      DisplayBeep(NULL);
      LibFreePooled(mempool,tempnodes,26*sizeof(struct TempNode));
      LibFreePooled(mempool,tempaccessnodes,nodes*sizeof(struct TempNode));
      return;
   }

   /* No nodes? */

   if(!config.CNodeList.First)
   {
      LT_SetAttributes(parthandle,5000,GA_Disabled,TRUE,TAG_END);
      LT_SetAttributes(parthandle,5001,GA_Disabled,TRUE,TAG_END);
   }

   Groups_SetCurrent(0);

   for(;;)
   {
      while(IntuiMessage=(struct IntuiMessage *)LT_GetIMsg(parthandle))
      {
         class=IntuiMessage->Class;
         code=IntuiMessage->Code;
         iaddress=IntuiMessage->IAddress;
         qualifier=IntuiMessage->Qualifier;

         LT_ReplyIMsg(IntuiMessage);

         switch(class)
         {
            case IDCMP_RAWKEY:         if(code == RAWKEY_TAB) LT_Activate(parthandle,4001);
                                       break;

            case IDCMP_IDCMPUPDATE:    if(Groups_CurrentNode)
                                       {
                                          switch(((struct Gadget *)iaddress)->GadgetID)
                                          {
                                             case 5000:
                                                cnode=(struct ConfigNode *)Groups_CurrentAccessNode->UserData;

                                                if(CheckFlags('A'+Groups_CurrentNode->num,cnode->FullAccessGroups))
                                                   Groups_SetAccess(2);

                                                else if(CheckFlags('A'+Groups_CurrentNode->num,cnode->ReadOnlyGroups))
                                                   Groups_SetAccess(3);

                                                else if(CheckFlags('A'+Groups_CurrentNode->num,cnode->WriteOnlyGroups))
                                                   Groups_SetAccess(0);

                                                else
                                                   Groups_SetAccess(1);

                                                break;
                                          }
                                       }
                                       break;

            case IDCMP_GADGETUP:       switch(((struct Gadget *)iaddress)->GadgetID)
                                       {
                                             case 4001:
                                                c=Groups_CurrentNode->num;
                                                LT_SetAttributes(parthandle,4000,GTLV_Labels,~0,TAG_END);
                                                sprintf(tempnodes[c].buf,"%lc: %s",'A'+c,getgadgetstring((struct Gadget *)iaddress));
                                                strcpy(config.cfg_GroupNames[c],getgadgetstring((struct Gadget *)iaddress));
                                                LT_SetAttributes(parthandle,4000,GTLV_Labels,&Groups_TempList,TAG_END);
                                                config.configchanged=TRUE;
                                                break;

                                             case 4000:
                                                Groups_UpdateConfig();
                                                Groups_SetCurrent(code);
                                                break;

                                             case 5000:
                                                Groups_SetCurrentAccess(code);
                                                break;

                                             case 5001:
                                                Groups_SetAccess(code);
                                                break;
                                       }
                                       break;

            case IDCMP_CLOSEWINDOW:   Groups_UpdateConfig();
                                      ClearMenuStrip(parthandle->Window);
                                      LT_DeleteHandle(parthandle);
                                      parthandle=NULL;

                                      LibFreePooled(mempool,tempnodes,26*sizeof(struct TempNode));
                                      LibFreePooled(mempool,tempaccessnodes,nodes*sizeof(struct TempNode));
                                      return;

         }
      }
      WaitPort(partwin->UserPort);
   }
}
