/* qdatePanel.c 
 *
 *  defines the GUIFront characteristics of the qdate panel
 */
#include <exec/types.h>
#include <exec/lists.h>
#include <exec/nodes.h>
#include <exec/memory.h>
#include <stdio.h>
#include <stdlib.h>
#include <intuition/gadgetclass.h>
#include <clib/alib_protos.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include "amiCheck.h"
#include "qdatePanel.h"
#include "dataBase.h"
#include "enterPanel.h"
#include "regGadget.h"

/* prototypes */
BOOL QDateHandleGadget(struct IntuiMessage *);
BOOL QDateHandleSlide(struct IntuiMessage *);
void QDateInit(char *);
void QDateUpdateEasy(BOOL);
dateNode *QDateSlot(UWORD, UBYTE, UBYTE);

ULONG qdateSel = ~0;
struct Window *qdateWin = NULL;
GUIFront *qdateGUI;
static BOOL done;
static BOOL useme;
BOOL easydate;
dateType edate;

/* quick configure of some gadgets */
static const struct TagItem sdaytags[] =
{
    {GTSL_Min, 1},
    {GTSL_Max, 31},
    {GA_Immediate, TRUE},
    {TAG_DONE},
};

static const struct TagItem smonthtags[] =
{
    {GTSL_Min, 1},
    {GTSL_Max, 12},
    {GA_Immediate, TRUE},
    {TAG_DONE},
};

static const struct TagItem syeartags[] =
{
    {GTSL_Min, 1970},
    {GTSL_Max, 2070},
    {GA_Immediate, TRUE},
    {TAG_DONE},
};


/* define gadgetspec */
GadgetSpec QDgadgetspecs[] = 
{
	{LISTVIEW_KIND,DATESIZE+2,0, {0,0,0,0,NULL,NULL,GID_QDATELIST,
		PLACETEXT_ABOVE},ListView,GS_DefaultTags},

     	{SLIDER_KIND, 12,0, {0,0,0,0,NULL,NULL,GID_QDATEDAYSLIDE,
		PLACETEXT_LEFT},sdaytags,GS_DefaultTags},
	
	{SLIDER_KIND, 12,0, {0,0,0,0,NULL,NULL,GID_QDATEMONTHSLIDE,
		PLACETEXT_LEFT},smonthtags,GS_DefaultTags}, 

	{SLIDER_KIND, 12,0, {0,0,0,0,NULL,NULL,GID_QDATEYEARSLIDE,
		PLACETEXT_LEFT},syeartags,GS_DefaultTags},

	{NUMBER_KIND, 4,0, {0,0,0,0,"Day",NULL,GID_QDATEDAY,
		PLACETEXT_LEFT},NumBorder,GS_DefaultTags},

	{TEXT_KIND, 4,0, {0,0,0,0,"Month",NULL,GID_QDATEMONTH,
		PLACETEXT_LEFT},TxtBorder,GS_DefaultTags},

	{NUMBER_KIND, 4,0, {0,0,0,0,"Year",NULL,GID_QDATEYEAR,
		PLACETEXT_LEFT},NumBorder,GS_DefaultTags},

	{BUTTON_KIND, 6,0, {0,0,0,0,"_OK",NULL,GID_QDATEOK,
		PLACETEXT_IN},NULL,GS_DefaultTags},

};

/* set up array of pointers to our specs */
GadgetSpec *QD_DateSpecs[] =
{
        &QDgadgetspecs[0],
        &QDgadgetspecs[1],
        &QDgadgetspecs[2],
        &QDgadgetspecs[3],
        &QDgadgetspecs[4],
        &QDgadgetspecs[5],
        &QDgadgetspecs[6],
        &QDgadgetspecs[7],
        NULL,
};


/* define the layout of this panel */
ULONG QD_DatePanel[] =
{
   GUIL_Flags, GUILF_PropShare | GUILF_EqualWidth,
        
  GUIL_HorizGroup,1,
	GUIL_Flags, GUILF_EqualHeight,
	GUIL_FrameType, GUILFT_Recess,

	GUIL_VertGroup,1,
		GUIL_FrameType, GUILFT_Ridge,
/*		GUIL_FrameHeadline, "Easy Date",*/

		GUIL_VertGroup,1,
			GUIL_Flags, GUILF_LabelAlign | GUILF_EqualWidth,	

			GUIL_HorizGroup,0,
				GUIL_GadgetSpecID, GID_QDATEMONTH,
				GUIL_GadgetSpecID, GID_QDATEMONTHSLIDE,
			TAG_DONE,

			GUIL_HorizGroup,0,
				GUIL_GadgetSpecID, GID_QDATEDAY,
				GUIL_GadgetSpecID, GID_QDATEDAYSLIDE,
			TAG_DONE,

			GUIL_HorizGroup,0,
				GUIL_GadgetSpecID, GID_QDATEYEAR,
				GUIL_GadgetSpecID, GID_QDATEYEARSLIDE,
			TAG_DONE,
		TAG_DONE,

		/*GUIL_GadgetSpecID, GID_QDATELIST,*/
	TAG_DONE,

	GUIL_VertGroup,1,
	        GUIL_FrameType, GUILFT_Ridge,
/*		GUIL_FrameHeadline, "Quick Date", */                         

		GUIL_GadgetSpecID, GID_QDATELIST,
        TAG_DONE,
  TAG_DONE,
   
    GUIL_HorizGroup,1,
        GUIL_Flags, GUILF_EqualSize | GUILF_EqualWidth,
        
           GUIL_GadgetSpecID, GID_QDATEOK,
           
    TAG_DONE,                     
TAG_DONE,       
};

/****************************************************
* QDateGUI
*
*	create gui for this panel
*****************************************************/
BOOL QDateGUI(char *currdate)
{
 UWORD ordinal;
 BOOL noreply; 
 ULONG signal;

   useme = done = FALSE;

   /* lock edit window */
   GF_LockGUI(entryGUI);

   /* bring up this gui */
   GF_SetGUIAttr(qdateGUI, GUI_OpenGUI, TRUE, TAG_DONE);
   
   /* grab window */
   GF_GetGUIAttr(qdateGUI,GUI_Window,&qdateWin,TAG_DONE);

   QDateInit(currdate);

   /* 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:
                                        done = TRUE;
                                        break;

				case IDCMP_RAWKEY:
					if (GF_ProcessListView(qdateGUI,QD_DateSpecs[GID_QDATELIST],
						imsg,&ordinal)) {
							qdateSel = ordinal;	
					}
					else AmiHelpKey(imsg,QUICKDATE_PANEL);
					break;

				case IDCMP_GADGETUP:
					noreply = FALSE;
					done=QDateHandleGadget(imsg);
					break;

				case IDCMP_GADGETDOWN:
					done = QDateHandleSlide(imsg);
					break;

				case IDCMP_MOUSEMOVE:
					done=QDateHandleSlide(imsg);
					break;
	            }

		    if (noreply) GF_ReplyIMsg(imsg);

         	}
  }

  /* detach list */
  GF_SetGadgetAttrs(qdateGUI,QDgadgetspecs[GID_QDATELIST].gs_Gadget,
	GTLV_Labels, ~0,
	TAG_DONE);

  /* close window */
  GF_SetGUIAttr(qdateGUI, GUI_OpenGUI, FALSE, TAG_DONE);            
  qdateWin = NULL;
      
  /* unlock edit window */
  GF_UnlockGUI(entryGUI);

  return (useme);
}

/***************************************************
* QDateHandleSlide....
*
* 	set slide
****************************************************/
BOOL QDateHandleSlide(struct IntuiMessage *imsg)
{
BOOL done = FALSE;
struct Gadget *gad = (struct Gadget *)(imsg->IAddress);
UWORD code = imsg->Code;

 switch (gad->GadgetID) {
	case GID_QDATEYEARSLIDE:
		edate.year = code;
		QDateUpdateEasy(FALSE);
		break;

	case GID_QDATEMONTHSLIDE:
		edate.month = code-1;
		if (edate.day > daysinmonth[edate.month])
			edate.day = daysinmonth[edate.month];

		QDateUpdateEasy(TRUE);
		break;

	case GID_QDATEDAYSLIDE:
		edate.day = code;
		QDateUpdateEasy(FALSE);
		break;
 }

 return (done);
}

/***************************************************
* QDateHandleGadget....
*
* 	double clicks change ord val.
****************************************************/
BOOL QDateHandleGadget(struct IntuiMessage *imsg)
{
BOOL done = FALSE;
struct Gadget *gad = (struct Gadget *)(imsg->IAddress);
UWORD code = imsg->Code;
dateNode *date;

 switch (gad->GadgetID) {

	case GID_QDATEOK:
		easydate = TRUE;
		useme = TRUE;
		done=TRUE;
		edate.month++;
		break;

	case GID_QDATELIST:
		easydate = FALSE;
		qdateSel = code;

		date = (dateNode *)DataOrd2Node((struct List *)&datelist,qdateSel);
		memcpy(&edate,&date->date,sizeof(dateType));
		edate.month--;

		if (edate.year < 1970) edate.year = 1970;
		if (edate.year > 2070) edate.year = 2070;

		QDateUpdateEasy(TRUE);

		/* now set sliders */
 		GF_SetGadgetAttrs(qdateGUI,QDgadgetspecs[GID_QDATEDAYSLIDE].gs_Gadget,
			GTSL_Level,edate.day,
			TAG_DONE);

 		GF_SetGadgetAttrs(qdateGUI,QDgadgetspecs[GID_QDATEMONTHSLIDE].gs_Gadget,
			GTSL_Level,edate.month+1,
			TAG_DONE);

 		GF_SetGadgetAttrs(qdateGUI,QDgadgetspecs[GID_QDATEYEARSLIDE].gs_Gadget,
			GTSL_Level,edate.year,
			TAG_DONE);

		break;
 }

 return (done);
}

/***********************************************************
* QDateUpdateEasy()
*
*	Update the easy-date settings
************************************************************/
void QDateUpdateEasy(BOOL adjust)
{

	GF_SetGadgetAttrs(qdateGUI,QDgadgetspecs[GID_QDATEDAY].gs_Gadget,
			GTNM_Number,edate.day,
			TAG_DONE);

	GF_SetGadgetAttrs(qdateGUI,QDgadgetspecs[GID_QDATEMONTH].gs_Gadget,
			GTTX_Text,easymonths[edate.month],
			TAG_DONE);

	GF_SetGadgetAttrs(qdateGUI,QDgadgetspecs[GID_QDATEYEAR].gs_Gadget,
			GTNM_Number,edate.year,
			TAG_DONE);

	/*adjust days for month? */
	if (adjust == TRUE) {
		GF_SetGadgetAttrs(qdateGUI,QDgadgetspecs[GID_QDATEDAYSLIDE].gs_Gadget,
			GTSL_Max, daysinmonth[edate.month],
			TAG_DONE);
	}
}

/***********************************************************
* QDateInit()
*
*
************************************************************/
void QDateInit(char *datestr)
{
 char newstr[DATESIZE+1];
 dateNode *date;

 GF_SetGadgetAttrs(qdateGUI,QDgadgetspecs[GID_QDATELIST].gs_Gadget,
	GTLV_Labels, &datelist,
	GTLV_Selected, ~0,
	/*GTLV_MakeVisible, qdateSel,*/
	TAG_DONE);
   
 if (qdateSel != ~0)
 GF_SetGadgetAttrs(qdateGUI,QDgadgetspecs[GID_QDATELIST].gs_Gadget,
	GTLV_MakeVisible, qdateSel,
	TAG_DONE);


 /* now fill in easy-date gadgets */
 if (DataVerifyDate(datestr,newstr)) {
 	DataStoreDate(&edate,newstr);
 }
 else 	{
	date = (dateNode *)DataOrd2Node((struct List *)&datelist,qdateSel);
	memcpy(&edate,&date->date,sizeof(dateType));

	GF_SetGadgetAttrs(qdateGUI,QDgadgetspecs[GID_QDATELIST].gs_Gadget,
		GTLV_Selected, qdateSel,
		GTLV_MakeVisible, qdateSel,
		TAG_DONE);
 }

 edate.month--;

 if (edate.year < 1970) edate.year = 1970;
 if (edate.year > 2070) edate.year = 2070;

 QDateUpdateEasy(TRUE); 

 /* now set sliders */
 GF_SetGadgetAttrs(qdateGUI,QDgadgetspecs[GID_QDATEDAYSLIDE].gs_Gadget,
	GTSL_Level,edate.day,
	TAG_DONE);

 GF_SetGadgetAttrs(qdateGUI,QDgadgetspecs[GID_QDATEMONTHSLIDE].gs_Gadget,
	GTSL_Level,edate.month+1,
	TAG_DONE);

 GF_SetGadgetAttrs(qdateGUI,QDgadgetspecs[GID_QDATEYEARSLIDE].gs_Gadget,
	GTSL_Level,edate.year,
	TAG_DONE);

}

/***********************************************************
* QDateAdd()
*
*	Adds a date to the date list
************************************************************/
void QDateAdd(dateType *new)
{
 dateNode *node, *parent = NULL;

 /* find a parent for this new node */
 if ( (parent = QDateSlot(new->year,new->month, new->day)) == NULL)
	return;

 if ((node = AllocVec(sizeof(dateNode),MEMF_CLEAR))){
	memcpy(&node->date,new,sizeof(dateType));

	/* build date string */
	DataBuildDate(&node->date,node->dateStr);

	node->node.ln_Type = NT_USER;
	node->node.ln_Pri = 0;
	node->node.ln_Name = node->dateStr;

	Insert(&datelist,(struct Node *)node, (struct Node *)parent);
	qdateSel = DataNode2Ord(&datelist,node->dateStr);
 }
 else return;
}

/***********************************************************
* QDateSlot()
*
*	Locate a parent node for the current date 
***********************************************************/
dateNode *QDateSlot(USHORT year, UBYTE month, UBYTE day)
{
 dateNode *temp = (dateNode *)datelist.lh_Head, *next;

 /* is this the first date? */
 if (IsListEmpty(&datelist)) {
	return ((dateNode *)&datelist);
 }

 /* loop through each node from old to new */
 while (next = (dateNode *)(temp->node.ln_Succ)) {
	/* redundant? */
	if (year == temp->date.year && month == temp->date.month && day == temp->date.day)
		return (NULL);

   	/* am I older than the current node? */
	if (year < temp->date.year ||
	   (year == temp->date.year && month < temp->date.month) ||
	   (year == temp->date.year && month == temp->date.month && day < temp->date.day)) {
		return ((dateNode *)temp->node.ln_Pred);
	}

	temp = next;
 }
 
 /* stuff at end! */
 return (temp);
}

/*********************************************************
* QDateNewFormat()
*
*	Updates the list to the new date format
**********************************************************/
void QDateNewFormat(void)
{
 dateNode *work = NULL;

 while ( (work = (dateNode *)DataGetNext(&datelist,work)) != NULL) {
	DataBuildDate(&work->date,work->dateStr);
 }
}
