#include <CrashPrefs.h>

struct List changelist;

ULONG changenum,currentchange;
struct Change *changenode;

STRPTR prilabels[]={"Hold","Normal","Direct","Crash",NULL};

struct Hook ChangeHelpHook = { {NULL}, HelpHookEntry,NULL,HELP_CHANGE};

UBYTE testchange[30];

void SetChange(ULONG num)
{
   ULONG c;

   if(changenum == 0)
   {
      LT_SetAttributes(parthandle,4712,GA_Disabled,TRUE,TAG_END);
      LT_SetAttributes(parthandle,11,GA_Disabled,TRUE,TAG_END);
      LT_SetAttributes(parthandle,12,GA_Disabled,TRUE,TAG_END);
      LT_SetAttributes(parthandle,13,GA_Disabled,TRUE,TAG_END);
      LT_SetAttributes(parthandle,50,GA_Disabled,TRUE,TAG_END);
      LT_SetAttributes(parthandle,51,GA_Disabled,TRUE,TAG_END);
      LT_SetAttributes(parthandle,52,GA_Disabled,TRUE,TAG_END);
      LT_SetAttributes(parthandle,53,GA_Disabled,TRUE,TAG_END);
      LT_SetAttributes(parthandle,54,GA_Disabled,TRUE,TAG_END);
   }

   if(num!=-1)
   {
      if(changenum)
      {
         LT_SetAttributes(parthandle,11,GA_Disabled,FALSE,TAG_END);
         LT_SetAttributes(parthandle,4712,GA_Disabled,FALSE,TAG_END);
      }
      else
      {
         LT_SetAttributes(parthandle,11,GA_Disabled,TRUE,TAG_END);
         LT_SetAttributes(parthandle,4712,GA_Disabled,TRUE,TAG_END);
      }

      changenode=ChangeList.First;
      for(c=0;c<num;c++) changenode=changenode->Next;

      if(num!=0)                 LT_SetAttributes(parthandle,12,GA_Disabled,FALSE,TAG_END);
      else                       LT_SetAttributes(parthandle,12,GA_Disabled,TRUE,TAG_END);

      if(num!=changenum-1)       LT_SetAttributes(parthandle,13,GA_Disabled,FALSE,TAG_END);
      else                       LT_SetAttributes(parthandle,13,GA_Disabled,TRUE,TAG_END);

      LT_SetAttributes(parthandle,50,GA_Disabled,FALSE,TAG_END);
      LT_SetAttributes(parthandle,51,GA_Disabled,FALSE,TAG_END);
      LT_SetAttributes(parthandle,52,GA_Disabled,FALSE,TAG_END);
      LT_SetAttributes(parthandle,53,GA_Disabled,FALSE,TAG_END);
      LT_SetAttributes(parthandle,54,GA_Disabled,FALSE,TAG_END);

      LT_SetAttributes(parthandle,50,GTCB_Checked,changenode->ChangeNormal,TAG_END);
      LT_SetAttributes(parthandle,51,GTCB_Checked,changenode->ChangeCrash,TAG_END);
      LT_SetAttributes(parthandle,52,GTCB_Checked,changenode->ChangeDirect,TAG_END);
      LT_SetAttributes(parthandle,53,GTCB_Checked,changenode->ChangeHold,TAG_END);
      LT_SetAttributes(parthandle,54,GTCY_Active,changenode->DestPri-1,TAG_END);
   }
   currentchange=num;
}

void RefreshChangelist(void)
{
   struct TempNode *tempnode;
   struct Change *change;

   LT_SetAttributes(parthandle,4711,GTLV_Labels,~0,TAG_END);
   FreeTempNodes(&changelist);

   changenum=0;

   for(change=ChangeList.First;change;change=change->Next)
   {
      if(!(tempnode=(struct TempNode *)AllocMem(sizeof(struct TempNode),MEMF_CLEAR)))
      {
         DisplayBeep(NULL);
         FreeTempNodes(&changelist);
         return;
      }

      Print4DPat(&change->Pattern,tempnode->buf);
      tempnode->Node.ln_Name=tempnode->buf;
      AddTail(&changelist,(struct Node *)tempnode);
      changenum++;
   }

   LT_SetAttributes(parthandle,4711,GTLV_Labels,&changelist,TAG_END);
}

void AddChange(void)
{
   struct Change *change;
   struct Node4DPat n4dpat;
   UBYTE buf[200];
   BOOL res;
   BOOL kg;

   kg=TRUE;
   buf[0]=0;

   while(kg)
   {
      res=rtGetString(buf,50,"Add change pattern",NULL,RT_Window,partwin,
                                                      RT_WaitPointer, TRUE,
                                                      RT_LockWindow, TRUE,
                                                      TAG_END);

      if(!res)
         return;

      kg=FALSE;

      if(!Parse4DPat(buf,&n4dpat))
      {
         rtEZRequestTags("Invalid node pattern","_Ok",NULL,NULL,RT_Underscore,'_',
                                                                RT_Window,partwin,
                                                                RT_WaitPointer, TRUE,
                                                                RT_LockWindow, TRUE,
                                                                TAG_END);
         kg=TRUE;
      }
   }

   if(!res)
      return;

   if(change=(struct Change *)AllocMem(sizeof(struct Change),MEMF_CLEAR))
   {
      jbAddNode(&ChangeList,(struct jbNode *)change);
      Copy4DPat(&change->Pattern,&n4dpat);
      change->DestPri=PKTS_NORMAL;
      RefreshChangelist();
      SetChange(changenum-1);
      LT_SetAttributes(parthandle,4711,GTLV_Selected,currentchange,GTLV_MakeVisible,currentchange,TAG_END);
      saveconfig=TRUE;
   }
   else
   {
      DisplayBeep(NULL);
   }
}

void RemChange(void)
{
   ULONG c,tmp;
   struct Change *change;
   UBYTE buf[100],buf2[100];
   BOOL res;

   change=ChangeList.First;
   for(c=0;c<currentchange;c++) change=change->Next;

   Print4DPat(&change->Pattern,buf2);

   sprintf(buf,"Do you really want to remove the change statement for \"%s\"?",
      buf2);

   res=rtEZRequestTags(buf,"_Remove|_Cancel",NULL,NULL,RT_Underscore,'_',
                                                       RT_Window,partwin,
                                                       RT_WaitPointer,TRUE,
                                                       RT_LockWindow, TRUE,
                                                       RTEZ_Flags, EZREQF_CENTERTEXT | EZREQF_NORETURNKEY,
                                                       TAG_END);

   if(!res)
      return;

   tmp=currentchange;
   jbFreeNode(&ChangeList,(struct jbNode *)change,sizeof(struct Change));
   RefreshChangelist();
   if(tmp == changenum) tmp--;
   SetChange(tmp);
   saveconfig=TRUE;
}

UBYTE testchangebuf[40];

ChangeType(struct Node4D *dest,UBYTE pri)
{
   struct Change *change;
   UBYTE newpri;
   BOOL ispattern;

   newpri=pri;

   for(change=ChangeList.First;change;change=change->Next)
   {
      if(Compare4DPat(&change->Pattern,dest)==0)
      {
         ispattern=FALSE;

         if(pri == PKTS_ECHOMAIL && change->ChangeNormal == TRUE) ispattern=TRUE;
         if(pri == PKTS_NORMAL   && change->ChangeNormal == TRUE) ispattern=TRUE;
         if(pri == PKTS_CRASH    && change->ChangeCrash  == TRUE) ispattern=TRUE;
         if(pri == PKTS_DIRECT   && change->ChangeDirect == TRUE) ispattern=TRUE;
         if(pri == PKTS_HOLD     && change->ChangeHold   == TRUE) ispattern=TRUE;

         if(ispattern)
         {
            if(pri == PKTS_ECHOMAIL && change->DestPri == PKTS_NORMAL)
               newpri=pri;

            else
               newpri=change->DestPri;
         }
      }
   }

   return(newpri);
}

void TestChange(void)
{
   struct Node4D n4d;
   ULONG oldpri,newpri;
   BOOL neednl;
   struct Change *change;
   UBYTE errbuf[100];
   
   if(testchange[0]==0)
      return;

   Parse4D(testchange,&n4d);
   oldpri=LT_GetAttributes(parthandle,61,TAG_END)+1;

   neednl=FALSE;

   for(change=ChangeList.First;change;change=change->Next)
      if(change->Pattern.Type == PAT_REGION || change->Pattern.Type == PAT_HUB) neednl=TRUE;

   if(neednl)
   {
      if(cfg_NodeList[0]==0)
      {
         strcpy(testchangebuf,"Nodelist required");
         LT_SetAttributes(parthandle,62,GTTX_Text,testchangebuf,TAG_END);
         return;
      }
      else
      {
         if(!nlStart(errbuf))
         {
            strcpy(testchangebuf,"Nodelist error");
            LT_SetAttributes(parthandle,62,GTTX_Text,testchangebuf,TAG_END);
            return;
         }
      }
   }

   newpri=ChangeType(&n4d,oldpri);
   strcpy(testchangebuf,prilabels[newpri-1]);

   if(neednl && cfg_NodeList[0]!=0)
      nlEnd();

   LT_SetAttributes(parthandle,62,GTTX_Text,testchangebuf,TAG_END);
}

void PartChange(void)
{
   ULONG class,code,tmp;
   struct IntuiMessage *IntuiMessage;
   struct TempNode *tempnode;
   APTR iaddress;
   ULONG c;
   UBYTE nodebuf[50];
   struct Node4DPat n4dpat;
   struct Node4D n4d;

   NewList(&changelist);

   currentchange=-1;
   testchange[0]=0;

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

   if(!parthandle)
   {
      FreeTempNodes(&changelist);
      return;
   }

   LT_New(parthandle,
      LA_Type,      HORIZONTAL_KIND,
      LA_LabelText, "Change",
      TAG_DONE);

      LT_New(parthandle,
         LA_Type,      VERTICAL_KIND,
         TAG_DONE);

         LT_New(parthandle,
            LA_Type,      STRING_KIND,
            GTST_MaxChars,199,
            LA_ID,        4712,
            LAST_Link,    4711,
            GA_Disabled,TRUE,
            TAG_DONE);

         LT_New(parthandle,
            LA_Type,       LISTVIEW_KIND,
            LA_Chars,      20,
            LALV_Lines,    10,
            LALV_CursorKey,TRUE,
            LALV_Link,     4712,
            GTLV_Labels,   &changelist,
            LALV_LockSize, TRUE,
            LA_ID,4711,
            TAG_DONE);

         LT_New(parthandle,
            LA_Type,      HORIZONTAL_KIND,
            LAGR_SameSize,TRUE,
            TAG_DONE);

            LT_New(parthandle,
               LA_Type,      VERTICAL_KIND,
               LAGR_SameSize,TRUE,
               TAG_DONE);

               LT_New(parthandle,
                  LA_Type,      BUTTON_KIND,
                  LA_LabelText, "Add...",
                  LA_Chars,10,
                  LA_ID,10,
                  TAG_DONE);

               LT_New(parthandle,
                  LA_Type,      BUTTON_KIND,
                  LA_LabelText, "Up",
                  GA_Disabled,TRUE,
                  LA_Chars,10,
                  LA_ID,12,
                  TAG_DONE);

            LT_EndGroup(parthandle);

            LT_New(parthandle,
               LA_Type,      VERTICAL_KIND,
               LAGR_SameSize,TRUE,
               TAG_DONE);

               LT_New(parthandle,
                  LA_Type,      BUTTON_KIND,
                  LA_LabelText, "Remove...",
                  LA_Chars,10,
                  GA_Disabled,TRUE,
                  LA_ID,11,
                  TAG_DONE);

               LT_New(parthandle,
                  LA_Type,      BUTTON_KIND,
                  LA_LabelText, "Down",
                  LA_Chars,10,
                  GA_Disabled,TRUE,
                  LA_ID,13,
                  TAG_DONE);

            LT_EndGroup(parthandle);

         LT_EndGroup(parthandle);

      LT_EndGroup(parthandle);

      LT_New(parthandle,
         LA_Type,      VERTICAL_KIND,
         LA_ExtraSpace,TRUE,
         TAG_DONE);

            LT_New(parthandle,
               LA_Type,      VERTICAL_KIND,
               TAG_DONE);

            LT_New(parthandle,
               LA_Type,      CHECKBOX_KIND,
               LA_LabelText, "Change Normal",
               GA_Disabled,TRUE,
               LA_Chars,20,
               LA_ID,50,
               TAG_DONE);

            LT_New(parthandle,
               LA_Type,      CHECKBOX_KIND,
               LA_LabelText, "Change Crash",
               GA_Disabled,TRUE,
               LA_Chars,20,
               LA_ID,51,
               TAG_DONE);

            LT_New(parthandle,
               LA_Type,      CHECKBOX_KIND,
               LA_LabelText, "Change Direct",
               GA_Disabled,TRUE,
               LA_Chars,20,
               LA_ID,52,
               TAG_DONE);

            LT_New(parthandle,
               LA_Type,      CHECKBOX_KIND,
               LA_LabelText, "Change Hold",
               GA_Disabled,TRUE,
               LA_Chars,20,
               LA_ID,53,
               TAG_DONE);

            LT_New(parthandle,
               LA_Type,      CYCLE_KIND,
               LA_LabelText, "Change to",
               GTCY_Labels,  prilabels,
               GA_Disabled,TRUE,
               LA_Chars,20,
               LA_ID,54,
               TAG_DONE);

            LT_EndGroup(parthandle);

            LT_New(parthandle,
               LA_Type,      VERTICAL_KIND,
               LA_ExtraSpace,TRUE,
               LA_LabelText, "Test change",
               TAG_DONE);

               LT_New(parthandle,
                  LA_Type,      STRING_KIND,
                  LA_LabelText, "Destination",
                  GTST_MaxChars,50,
                  LA_Chars,20,
                  LA_ID,60,
                  TAG_DONE);

               LT_New(parthandle,
                  LA_Type,      CYCLE_KIND,
                  LA_LabelText, "Type",
                  GTCY_Labels,  prilabels,
                  GTCY_Active,1,
                  LA_Chars,20,
                  LA_ID,61,
                  TAG_DONE);

               LT_New(parthandle,
                  LA_Type,      TEXT_KIND,
                  LA_LabelText, "New type",
                  GTTX_Border,TRUE,
                  LA_Chars,20,
                  LA_ID,62,
                  TAG_DONE);

            LT_EndGroup(parthandle);

      LT_EndGroup(parthandle);

   LT_EndGroup(parthandle);

   partwin=LT_Build(parthandle,LAWN_IDCMP,    IDCMP_CLOSEWINDOW|IDCMP_RAWKEY,
                               LAWN_Title,    "Change",
                               WA_Flags,      WFLG_ACTIVATE|WFLG_CLOSEGADGET|WFLG_DEPTHGADGET|WFLG_DRAGBAR|WFLG_NEWLOOKMENUS,
                               LAWN_HelpHook, &ChangeHelpHook,
                               TAG_END);

   if(!partwin)
   {
      LT_DeleteHandle(parthandle);
      DisplayBeep(NULL);
      FreeTempNodes(&changelist);
      return;
   }

   RefreshChangelist();

   if(changenum)
   {
      LT_SetAttributes(parthandle,4711,GTLV_Selected,0,TAG_END);
      SetChange(0);
   }

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

         LT_ReplyIMsg(IntuiMessage);

         switch(class)
         {
            case IDCMP_RAWKEY:         if(code == TAB) LT_Activate(parthandle,4712);
                                       break;
            case IDCMP_GADGETUP:       switch(((struct Gadget *)iaddress)->GadgetID)
                                       {
                                          case 10:
                                             AddChange();
                                             break;
                                          case 11:
                                             RemChange();
                                             break;
                                          case 12:
                                             if(currentchange != 0)
                                             {
                                                tmp=currentchange;
                                                MoveUp(&ChangeList,tmp);
                                                RefreshChangelist();
                                                SetChange(tmp-1);
                                                LT_SetAttributes(parthandle,4711,
                                                   GTLV_Selected,currentchange,
                                                   GTLV_MakeVisible,currentchange,
                                                   TAG_END);
                                                saveconfig=TRUE;
                                             }
                                             break;
                                          case 13:
                                             if(currentchange != changenum-1)
                                             {
                                                tmp=currentchange;
                                                MoveDown(&ChangeList,tmp);
                                                RefreshChangelist();
                                                SetChange(tmp+1);
                                                LT_SetAttributes(parthandle,4711,
                                                   GTLV_Selected,currentchange,
                                                   GTLV_MakeVisible,currentchange,
                                                   TAG_END);
                                                saveconfig=TRUE;
                                             }
                                             break;
                                          case 50:
                                             if(changenode->ChangeNormal) changenode->ChangeNormal=FALSE;
                                             else                         changenode->ChangeNormal=TRUE;
                                             saveconfig=TRUE;
                                             break;
                                          case 51:
                                             if(changenode->ChangeCrash) changenode->ChangeCrash=FALSE;
                                             else                        changenode->ChangeCrash=TRUE;
                                             saveconfig=TRUE;
                                             break;
                                          case 52:
                                             if(changenode->ChangeDirect) changenode->ChangeDirect=FALSE;
                                             else                         changenode->ChangeDirect=TRUE;
                                             saveconfig=TRUE;
                                             break;
                                          case 53:
                                             if(changenode->ChangeHold) changenode->ChangeHold=FALSE;
                                             else                       changenode->ChangeHold=TRUE;
                                             saveconfig=TRUE;
                                             break;
                                          case 54:
                                             changenode->DestPri=code+1;
                                             saveconfig=TRUE;
                                             break;
                                          case 60:
                                          case 61:
                                             if(Parse4D((UBYTE *)LT_GetAttributes(parthandle,60,TAG_END),&n4d))
                                             {
                                                sprintf(testchange,"%lu:%lu/%lu.%lu",n4d.Zone,n4d.Net,n4d.Node,n4d.Point);
                                                LT_SetAttributes(parthandle,60,GTST_String,testchange,TAG_END);
                                             }
                                             else
                                             {
                                                DisplayBeep(NULL);
                                                LT_Activate(parthandle,60);
                                             }
                                             break;
                                          case 4711:
                                             SetChange(code);
                                             break;
                                          case 4712:
                                             if(!Parse4DPat(getgadgetstring((struct Gadget *)iaddress),&n4dpat))
                                             {
                                                DisplayBeep(NULL);
                                                LT_Activate(parthandle,4712);
                                             }
                                             else
                                             {
                                                Copy4DPat(&changenode->Pattern,&n4dpat);
                                                Print4DPat(&n4dpat,nodebuf);

                                                tempnode=changelist.lh_Head;
                                                for(c=0;c<currentchange;c++) tempnode=tempnode->Node.ln_Succ;

                                                LT_SetAttributes(parthandle,4711,GTLV_Labels,~0,TAG_END);
                                                strcpy(tempnode->buf,nodebuf);
                                                LT_SetAttributes(parthandle,4711,GTLV_Labels,&changelist,TAG_END);
                                                saveconfig=TRUE;
                                             }
                                             break;
                                       }
                                       TestChange();
                                       break;
            case IDCMP_CLOSEWINDOW:    LT_DeleteHandle(parthandle);
                                       parthandle=NULL;
                                       FreeTempNodes(&changelist);
                                       return;
         }
      }
      WaitPort(partwin->UserPort);
   }
}
