/* categoryPanel.c 
 *
 *  defines the GUIFront characteristics of the category panel 
 */
  
#include <stdio.h>  
#include <intuition/gadgetclass.h>
#include "amiCheck.h"
#include "regGadget.h"
#include "dataBase.h"
#include "categoryPanel.h"
#include "groupPanel.h"
#include <string.h>


/* prototypes */
BOOL CatHandleGadget(struct IntuiMessage *);
void CatInit(void);
void CatDisableGads(BOOL);
void CatDisableBGads(BOOL);

struct List tempcats;
struct List tempgroups;
BOOL catretval;
ExtErrorData CatExtData;
GUIFront *catGUI;
UWORD	catlistActive;
UWORD	grouplistActive;
struct Window *catWin;
BOOL updatecats = FALSE;

/* quick configure of some gadgets */
extern struct TagItem catList[], budgetList[];

/* define gadgetspec */
GadgetSpec CPgadgetspecs[] = 
{
	{LISTVIEW_KIND,25,8, {0,0,0,0,NULL,NULL,GID_CPCATLIST,
		PLACETEXT_ABOVE},catList,GS_DefaultTags},

        {BUTTON_KIND,0,0,{0,0,0,0,"_New", NULL, GID_CPNEW,         
                PLACETEXT_IN}, NULL, GS_DefaultTags},

        {BUTTON_KIND,0,0,{0,0,0,0,"_Remove", NULL, GID_CPDEL,         
                PLACETEXT_IN}, NULL, GS_DefaultTags},

        {STRING_KIND,20,0,{0,0,0,0,NULL, NULL, GID_CPEDIT,         
                PLACETEXT_IN}, NULL, GS_DefaultTags},

        {BUTTON_KIND,0,0,{0,0,0,0,"_Up", NULL, GID_CPUP,         
                PLACETEXT_IN}, NULL, GS_DefaultTags},

        {BUTTON_KIND,0,0,{0,0,0,0,"_Down", NULL, GID_CPDOWN,         
                PLACETEXT_IN}, NULL, GS_DefaultTags},

        {BUTTON_KIND,0,0,{0,0,0,0,"_Top", NULL, GID_CPTOP,         
                PLACETEXT_IN}, NULL, GS_DefaultTags},

        {BUTTON_KIND,0,0,{0,0,0,0,"_Bottom", NULL, GID_CPBOTTOM,         
                PLACETEXT_IN}, NULL, GS_DefaultTags},

        {BUTTON_KIND,0,0,{0,0,0,0,"_OK", NULL, GID_CPOK,         
                PLACETEXT_IN}, NULL, GS_DefaultTags},

        {BUTTON_KIND,0,0,{0,0,0,0,"_Cancel", NULL, GID_CPCANCEL,        
                PLACETEXT_IN}, NULL, GS_DefaultTags},

	{LISTVIEW_KIND,25,8, {0,0,0,0,NULL,NULL,GID_CPBUDGETLIST,
		PLACETEXT_ABOVE},budgetList,GS_DefaultTags},

        {BUTTON_KIND,0,0,{0,0,0,0,"New", NULL, GID_CPBNEW,         
                PLACETEXT_IN}, NULL, GS_DefaultTags},

        {BUTTON_KIND,0,0,{0,0,0,0,"Remove", NULL, GID_CPBDEL,         
                PLACETEXT_IN}, NULL, GS_DefaultTags},

        {STRING_KIND,20,0,{0,0,0,0,NULL, NULL, GID_CPBEDIT,         
                PLACETEXT_IN}, NULL, GS_DefaultTags},

        {BUTTON_KIND,0,0,{0,0,0,0,"Up", NULL, GID_CPBUP,         
                PLACETEXT_IN}, NULL, GS_DefaultTags},

        {BUTTON_KIND,0,0,{0,0,0,0,"Down", NULL, GID_CPBDOWN,         
                PLACETEXT_IN}, NULL, GS_DefaultTags},

        {BUTTON_KIND,0,0,{0,0,0,0,"Top", NULL, GID_CPBTOP,         
                PLACETEXT_IN}, NULL, GS_DefaultTags},

        {BUTTON_KIND,0,0,{0,0,0,0,"Bottom", NULL, GID_CPBBOTTOM,         
                PLACETEXT_IN}, NULL, GS_DefaultTags},

        {BUTTON_KIND,0,0,{0,0,0,0,"Edit", NULL, GID_CPBBUILD,         
                PLACETEXT_IN}, NULL, GS_DefaultTags},
};

struct TagItem catList[] =
{
        {GTLV_ShowSelected, &CPgadgetspecs[GID_CPEDIT]},
        {TAG_DONE},
};

struct TagItem budgetList[] =
{
        {GTLV_ShowSelected, &CPgadgetspecs[GID_CPBEDIT]},
        {TAG_DONE},
};

/* set up array of pointers to our specs */
GadgetSpec *CP_CatSpecs[] =
{
        &CPgadgetspecs[0],
        &CPgadgetspecs[1],
        &CPgadgetspecs[2],
        &CPgadgetspecs[3],
        &CPgadgetspecs[4],
        &CPgadgetspecs[5],
        &CPgadgetspecs[6],
        &CPgadgetspecs[7],
        &CPgadgetspecs[8],
        &CPgadgetspecs[9],
        &CPgadgetspecs[10],
        &CPgadgetspecs[11],
        &CPgadgetspecs[12],
        &CPgadgetspecs[13],
        &CPgadgetspecs[14],
        &CPgadgetspecs[15],
        &CPgadgetspecs[16],
        &CPgadgetspecs[17],
        &CPgadgetspecs[18],

        NULL,
};


/* define the layout of this panel */
ULONG CP_CatPanel[] =
{
   GUIL_Flags, GUILF_PropShare | GUILF_EqualWidth,

   GUIL_HorizGroup, 1,
        GUIL_Flags, GUILF_PropShare,
	GUIL_FrameType, GUILFT_Recess,
       
GUIL_HorizGroup,1, 
	GUIL_VertGroup, 1,

		GUIL_HorizGroup,1,
			GUIL_FrameType, GUILFT_Ridge,
			GUIL_FrameHeadline, "Categories",
			GUIL_GadgetSpecID, GID_CPCATLIST,

                	GUIL_VertGroup,1,
                        	GUIL_Flags, GUILF_PropShare | GUILF_EqualWidth | GUILF_EqualHeight,
                                              
				GUIL_GadgetSpecID, GID_CPUP,
				GUIL_GadgetSpecID, GID_CPDOWN,
				GUIL_GadgetSpecID, GID_CPTOP,
				GUIL_GadgetSpecID, GID_CPBOTTOM,
                	TAG_DONE,

		TAG_DONE,
	
		GUIL_HorizGroup,1,
			GUIL_FrameType, GUILFT_Ridge,
			GUIL_Flags, GUILF_EqualSize | GUILF_EqualWidth,
			GUIL_GadgetSpecID, GID_CPDEL,
			GUIL_GadgetSpecID, GID_CPNEW,
		TAG_DONE,

	TAG_DONE,

	GUIL_VertGroup, 1,

		GUIL_HorizGroup,1,
			GUIL_FrameType, GUILFT_Ridge,
			GUIL_FrameHeadline, "Budget Groups",
			GUIL_GadgetSpecID, GID_CPBUDGETLIST,

                	GUIL_VertGroup,1,
                        	GUIL_Flags, GUILF_PropShare | GUILF_EqualWidth | GUILF_EqualHeight,
                                              
				GUIL_GadgetSpecID, GID_CPBUP,
				GUIL_GadgetSpecID, GID_CPBDOWN,
				GUIL_GadgetSpecID, GID_CPBTOP,
				GUIL_GadgetSpecID, GID_CPBBOTTOM,
                	TAG_DONE,

		TAG_DONE,
	
		GUIL_HorizGroup,1,
			GUIL_FrameType, GUILFT_Ridge,
			GUIL_Flags, GUILF_EqualSize | GUILF_EqualWidth,
			GUIL_GadgetSpecID, GID_CPBDEL,
			GUIL_GadgetSpecID, GID_CPBBUILD,
			GUIL_GadgetSpecID, GID_CPBNEW,
		TAG_DONE,

	TAG_DONE,

TAG_DONE,        
    TAG_DONE,
    
    GUIL_HorizGroup,1,
        GUIL_Flags, GUILF_EqualSize | GUILF_EqualWidth,
        
           GUIL_GadgetSpecID, GID_CPOK,
           GUIL_GadgetSpecID, GID_CPCANCEL,
           
    TAG_DONE,   
           
TAG_DONE,
};


/****************************************************
* CatGUI ()
*
*	Creates the GUI for the edit temp panel.
*****************************************************/
BOOL CatGUI(void)
{
 BOOL done = FALSE;
 BOOL noreply;
 UWORD ordinal;
 ULONG signal;
     
   AmiLock();

   /* install temporary list */
   NewList(&tempcats);
   NewList(&tempgroups);
   DataCopyGroupList(&grouplist, &tempgroups);
   DataCopyCatList(&tempcats,&categories);

   updatecats = FALSE;

		GF_SetGUIAttr(catGUI, GUI_OpenGUI, TRUE, TAG_DONE);
 		/* grab window */
 		GF_GetGUIAttr(catGUI,GUI_Window,&catWin,TAG_DONE);
		CatInit();


                /* Process input events */
                while (!done)
                {
                    struct IntuiMessage *imsg;

                    /* Wait for an event to occur */

                    signal = GF_Wait(guiapp,AmigaGuideSignal(agc));
		    if (signal & AmigaGuideSignal(agc)) {
			AmiHelpMsg();
			continue;
		    }

                    /* We only bother to listen for CLOSEWINDOW events.
                     * Of course, in a real application, you would be
                     * examining the Class field for IDCMP_GADGETUP
                     * messages and act accordingly.
                     */

                    while (imsg = GF_GetIMsg(guiapp))
                    {
			noreply = TRUE;
                        switch (imsg->Class) {
				case IDCMP_REFRESHWINDOW:
					RegRefresh(TRUE);
					break;

                                case IDCMP_CLOSEWINDOW:
					DataFreeList(&tempcats);
					DataFreeGroupCats(&tempgroups);
					DataFreeList(&tempgroups);
					NewList(&tempcats);
					NewList(&tempgroups);
                                        done = TRUE;
                                        break;

				case IDCMP_RAWKEY:
					if (GF_ProcessListView(catGUI,CP_CatSpecs[GID_CPCATLIST],
						imsg,&ordinal)) {
							catlistActive = ordinal;
							if (catlistActive >= DEFAULT_CATS)
								CatDisableGads(FALSE);
							else if (catlistActive < DEFAULT_TEMPS)
								CatDisableGads(TRUE);		
					}
					else AmiHelpKey(imsg,CAT_PANEL);
					break;

				case IDCMP_GADGETUP:
					noreply = FALSE;
					done=CatHandleGadget(imsg);
					break;
                        }
                                     
                              
                        if (noreply) GF_ReplyIMsg(imsg);
                    }
                }

   
   GF_SetGadgetAttrs(catGUI,CPgadgetspecs[GID_CPCATLIST].gs_Gadget,
			GTLV_Labels, ~0,
			TAG_DONE);

   GF_SetGadgetAttrs(catGUI,CPgadgetspecs[GID_CPBUDGETLIST].gs_Gadget,
			GTLV_Labels, ~0,
			TAG_DONE);

   GF_SetGUIAttr(catGUI, GUI_OpenGUI, FALSE, TAG_DONE);
   if (updatecats == TRUE) {
	     DataCopyGroupList(&tempgroups, &grouplist);
	     DataMoveCatList(&tempcats);
	     NewList(&tempcats);
	     NewList(&tempgroups);
   }

  AmiUnlock();
  return (catretval);
}

/***************************************************
* CatHandleGadget()
*
*	Handles gadget events for this panel
****************************************************/
BOOL  CatHandleGadget(struct IntuiMessage *imsg)
{
 BOOL done = FALSE;
 struct Gadget *gad = (struct Gadget *)(imsg->IAddress);
 UWORD tempOrd,code = imsg->Code;
 categoryNode tempcat;
 groupNode tempgroup, *groupPtr;
 editCatNode *temp;

 switch (gad->GadgetID) {
	
	case GID_CPCATLIST:
		catlistActive = code;
		if (catlistActive >= DEFAULT_CATS) 
			CatDisableGads(FALSE);
		else	CatDisableGads(TRUE);
		break;

	case GID_CPEDIT:
		if (catlistActive >= DEFAULT_CATS) {
		  if (DataIsUnique(catGUI, &tempcats,((struct StringInfo*)gad->SpecialInfo)->Buffer,
			TRUE,"Category name is not unique or invalid") ) {

			/* detach and modify this */
			temp = (editCatNode*)DataOrd2Node(&tempcats,catlistActive);
			GF_SetGadgetAttrs(catGUI,CPgadgetspecs[GID_CPCATLIST].gs_Gadget,
				GTLV_Labels, ~0,
				TAG_DONE);
			
			strcpy(temp->new.catname, ((struct StringInfo*)gad->SpecialInfo)->Buffer);

			/* now modify our group list */
			DataReplaceGroupCats(&tempgroups, &tempcats);

			GF_SetGadgetAttrs(catGUI,CPgadgetspecs[GID_CPCATLIST].gs_Gadget,
				GTLV_Labels, &tempcats,
				TAG_DONE);	
		  }
		  else {
			GF_ReplyIMsg(imsg);
			DataSitNSpin(CP_CatSpecs[GID_CPEDIT]->gs_Gadget,catWin);
			return (done);
		  }
		}
		break;

	case GID_CPNEW:
		strcpy(tempcat.catname,"NEW:RENAME ME");
		if (DataIsUnique(catGUI, &tempcats,tempcat.catname,TRUE,"You must rename the previous entry first")){
			/* detach and modify list */
			GF_SetGadgetAttrs(catGUI,CPgadgetspecs[GID_CPCATLIST].gs_Gadget,
				GTLV_Labels, ~0,
				TAG_DONE);
			
			temp=DataNewEditCat(&tempcats,&tempcat);
			catlistActive = DataNode2Ord(&tempcats,temp->new.catname);
					
			GF_SetGadgetAttrs(catGUI,CPgadgetspecs[GID_CPCATLIST].gs_Gadget,
				GTLV_Labels, &tempcats,
				GTLV_Selected, catlistActive,
				GTLV_MakeVisible, catlistActive,
				TAG_DONE);	

			CatDisableGads(FALSE);
		}
		break;

	case GID_CPDEL:
		DataListRemove(catGUI, CPgadgetspecs[GID_CPCATLIST].gs_Gadget,
			&tempcats, &catlistActive);

		/* now modify our group list */
		DataReplaceGroupCats(&tempgroups, &tempcats);

		if (catlistActive < DEFAULT_CATS)
			CatDisableGads(TRUE);		
		break;

	case GID_CPUP:
		if (catlistActive <= DEFAULT_CATS) break;
	
		DataListUp(catGUI,CPgadgetspecs[GID_CPCATLIST].gs_Gadget,	
			&tempcats, &catlistActive);
		break;

	case GID_CPDOWN:
		DataListDown(catGUI,CPgadgetspecs[GID_CPCATLIST].gs_Gadget,	
			&tempcats, &catlistActive);
		break;

	case GID_CPTOP:
		DataListTop(catGUI,CPgadgetspecs[GID_CPCATLIST].gs_Gadget,	
			&tempcats, &catlistActive, DEFAULT_CATS);
		break;

	case GID_CPBOTTOM:
		DataListBottom(catGUI,CPgadgetspecs[GID_CPCATLIST].gs_Gadget,	
			&tempcats, &catlistActive, DataCountNodes(&tempcats));
		break;

	case GID_CPBUDGETLIST:
		grouplistActive = code;
		CatDisableBGads(FALSE);
		break;

	case GID_CPBEDIT:
		if (grouplistActive == ~0) 
			break;

		  if (DataIsUnique(catGUI, &tempgroups,((struct StringInfo*)gad->SpecialInfo)->Buffer,
			TRUE,"Group name is not unique or invalid") ) {

			/* detach and modify this */
			groupPtr = (groupNode*)DataOrd2Node(&tempgroups,grouplistActive);
			GF_SetGadgetAttrs(catGUI,CPgadgetspecs[GID_CPBUDGETLIST].gs_Gadget,
				GTLV_Labels, ~0,
				TAG_DONE);
			
			strcpy(groupPtr->groupname, ((struct StringInfo*)gad->SpecialInfo)->Buffer);
			GF_SetGadgetAttrs(catGUI,CPgadgetspecs[GID_CPBUDGETLIST].gs_Gadget,
				GTLV_Labels, &tempgroups,
				TAG_DONE);	
		  }
		  else {
			GF_ReplyIMsg(imsg);
			DataSitNSpin(CP_CatSpecs[GID_CPBEDIT]->gs_Gadget,catWin);
			return (done);
		  }
		break;

	case GID_CPBNEW:
		strcpy(tempgroup.groupname,"NEW:RENAME ME");
		if (DataIsUnique(catGUI, &tempgroups,tempgroup.groupname,TRUE,"You must rename the previous entry first")){
			/* detach and modify list */
			GF_SetGadgetAttrs(catGUI,CPgadgetspecs[GID_CPBUDGETLIST].gs_Gadget,
				GTLV_Labels, ~0,
				TAG_DONE);
			
			groupPtr=DataNewGroup(&tempgroups,&tempgroup);

			grouplistActive = DataNode2Ord(&tempgroups,groupPtr->groupname);
					
			GF_SetGadgetAttrs(catGUI,CPgadgetspecs[GID_CPBUDGETLIST].gs_Gadget,
				GTLV_Labels, &tempgroups,
				GTLV_Selected, grouplistActive,
				GTLV_MakeVisible, grouplistActive,
				TAG_DONE);	

			CatDisableBGads(FALSE);
		}
		break;

	case GID_CPBDEL:
		/* first strip away group categories */
		groupPtr = (groupNode *)DataOrd2Node(&tempgroups,grouplistActive);
		DataFreeGroupCats(&groupPtr->catlist);

		/* now free up this node */
		DataListRemove(catGUI, CPgadgetspecs[GID_CPBUDGETLIST].gs_Gadget,
			&tempgroups, &grouplistActive);
		if (grouplistActive < 0)
			CatDisableBGads(TRUE);		
		break;

	case GID_CPBUP:
		DataListUp(catGUI,CPgadgetspecs[GID_CPBUDGETLIST].gs_Gadget,	
			&tempgroups, &grouplistActive);
		break;

	case GID_CPBDOWN:
		DataListDown(catGUI,CPgadgetspecs[GID_CPBUDGETLIST].gs_Gadget,	
			&tempgroups, &grouplistActive);
		break;

	case GID_CPBTOP:
		DataListTop(catGUI,CPgadgetspecs[GID_CPBUDGETLIST].gs_Gadget,	
			&tempgroups, &grouplistActive, 0);
		break;

	case GID_CPBBOTTOM:
		DataListBottom(catGUI,CPgadgetspecs[GID_CPBUDGETLIST].gs_Gadget,	
			&tempgroups, &grouplistActive, DataCountNodes(&tempgroups));
		break;

	case GID_CPBBUILD:
		/* lock this window */
		 GF_LockGUI(catGUI);

		groupPtr = (groupNode *)DataOrd2Node(&tempgroups,grouplistActive);
		GroupGUI(&tempcats,&groupPtr->catlist);

		/* unlock this window */
		GF_UnlockGUI(catGUI);
		break;

	case GID_CPCANCEL:
		DataFreeList(&tempcats);
		DataFreeGroupCats(&tempgroups);
		DataFreeList(&tempgroups);
		NewList(&tempcats);
		NewList(&tempgroups);
		done = TRUE;
		break;

	case GID_CPOK:
		amiChangedItems = TRUE;
		updatecats = done = TRUE;	
		break;
 }

 GF_ReplyIMsg(imsg);
 return (done);
}

/****************************************************
* CatInit()
*
*	Set up some globals
*****************************************************/
void CatInit(void)
{
	catretval = FALSE;
	catlistActive = ~0;
	grouplistActive = ~0;	

 /* grab window */
 GF_GetGUIAttr(catGUI,GUI_Window,&catWin,TAG_DONE);
 GF_SetGadgetAttrs(catGUI,CPgadgetspecs[GID_CPCATLIST].gs_Gadget,
			GTLV_Labels, &tempcats,
			GTLV_Selected,~0,
			TAG_DONE);

 GF_SetGadgetAttrs(catGUI,CPgadgetspecs[GID_CPBUDGETLIST].gs_Gadget,
			GTLV_Labels, &tempgroups,
			GTLV_Selected,~0,
			TAG_DONE);

 CatDisableGads(TRUE);
 CatDisableBGads(TRUE);
}

/****************************************************
* CatDisableGads()
*
*	Disable/Enable extra gadgets
*****************************************************/
void CatDisableGads(BOOL dis)
{
 GF_SetGadgetAttrs(catGUI,CPgadgetspecs[GID_CPDEL].gs_Gadget,
	GA_Disabled, dis,
	TAG_DONE);

 GF_SetGadgetAttrs(catGUI,CPgadgetspecs[GID_CPUP].gs_Gadget,
	GA_Disabled, dis,
	TAG_DONE);

 GF_SetGadgetAttrs(catGUI,CPgadgetspecs[GID_CPDOWN].gs_Gadget,
	GA_Disabled, dis,
	TAG_DONE);

 GF_SetGadgetAttrs(catGUI,CPgadgetspecs[GID_CPTOP].gs_Gadget,
	GA_Disabled, dis,
	TAG_DONE);

 GF_SetGadgetAttrs(catGUI,CPgadgetspecs[GID_CPBOTTOM].gs_Gadget,
	GA_Disabled, dis,
	TAG_DONE);
}

/****************************************************
* CatDisableBGads()
*
*	Disable/Enable extra gadgets
*****************************************************/
void CatDisableBGads(BOOL dis)
{
 GF_SetGadgetAttrs(catGUI,CPgadgetspecs[GID_CPBDEL].gs_Gadget,
	GA_Disabled, dis,
	TAG_DONE);

 GF_SetGadgetAttrs(catGUI,CPgadgetspecs[GID_CPBUP].gs_Gadget,
	GA_Disabled, dis,
	TAG_DONE);

 GF_SetGadgetAttrs(catGUI,CPgadgetspecs[GID_CPBDOWN].gs_Gadget,
	GA_Disabled, dis,
	TAG_DONE);

 GF_SetGadgetAttrs(catGUI,CPgadgetspecs[GID_CPBTOP].gs_Gadget,
	GA_Disabled, dis,
	TAG_DONE);

 GF_SetGadgetAttrs(catGUI,CPgadgetspecs[GID_CPBBOTTOM].gs_Gadget,
	GA_Disabled, dis,
	TAG_DONE);

 GF_SetGadgetAttrs(catGUI,CPgadgetspecs[GID_CPBBUILD].gs_Gadget,
	GA_Disabled, dis,
	TAG_DONE);

}
