#include <stdio.h>
#include <string.h>

#include <dos/dos.h>
#include <exec/lists.h>
#include <exec/memory.h>
#include <exec/types.h>
#include <intuition/intuition.h>
#include <libraries/gadtools.h>

#include <clib/alib_protos.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/intuition_protos.h>

#include "mod2midi.h"

#define LVNODE_ID 101
#define GAD_MODIFY 1
#define GAD_DONE 2
#define GAD_LISTVIEW 3
#define GAD_OK 4
#define GAD_CANCEL 5
#define GAD_ENTRY 6
#define GAD_TEXT 7

/* Function Prototypes */
int HandleGadgetMessages( struct Window *win, UBYTE HandlerMode );
struct lv_Node *NewLVNode( struct List *list, char *name );
void FreeList( struct List *list );
int ScrollChoice( string title, string *sp, int w );
string DialogBox( string *sp, string def );

extern char *version;

struct Library *IntuitionBase = NULL, *GadToolsBase = NULL;

struct lv_Node
{
	struct Node nn_Node;
	char Info[80];
};

char EnteredValue[31]; //Hate doing this, but everythings a kludge anyway
char defValue[31];
struct Gadget *gadENTRY;

int ScrollChoice( string title, string *sp, int w )
{
	struct Screen *screen;
	struct Window *win;

	void *vi = NULL;

	struct Gadget *gadContext = NULL;
	struct Gadget *gadList = NULL;
	struct Gadget *gadMODIFY, *gadDONE, *gadLISTVIEW;
	struct NewGadget gadNew;

	struct List *LView;

	struct TextAttr Topaz80 = { "topaz.font", 8, 0, 0 };

//	struct Process *process = NULL;

	int TBSize, Selected = -1;

	w++; //Maxmium width of entry list in characters

	IntuitionBase = OpenLibrary( "intuition.library", 37 );
	GadToolsBase = OpenLibrary( "gadtools.library", 37 );

	if ( IntuitionBase != NULL && GadToolsBase != NULL )
	{
//		process = (struct Process *)FindTask( NULL );
//		screen = ( (struct Window *)process->pr_WindowPtr )->WScreen;

		screen = LockPubScreen( NULL );

		if ( screen != NULL )
		{
			TBSize = screen->WBorTop + screen->Font->ta_YSize + 1;
			vi = GetVisualInfo( screen, TAG_END );

			LView = AllocMem( sizeof( struct List ), MEMF_CLEAR );
			if ( LView != NULL )
			{
				string *t = sp;

				NewList( LView );

				/* Add the names to the listview */
				while ( *t != NULL )
				{
					NewLVNode( LView, *(t++) );
				}

				gadList = CreateContext( &gadContext );

				gadNew.ng_LeftEdge		=	11;
				gadNew.ng_TopEdge			=	120 + TBSize;
				gadNew.ng_Width				=	69;
				gadNew.ng_Height			=	14;
				gadNew.ng_GadgetText = "Modify";
				gadNew.ng_TextAttr		=	&Topaz80;
				gadNew.ng_VisualInfo	=	vi;
				gadNew.ng_Flags				=	PLACETEXT_IN;
				gadNew.ng_GadgetID = GAD_MODIFY;
				gadMODIFY = gadList = CreateGadget( BUTTON_KIND, gadList, &gadNew,
																	 TAG_END );

				gadNew.ng_LeftEdge		=	99 + ( w * 8 - 80 ) - 69;
				gadNew.ng_GadgetText = "Done";
				gadNew.ng_GadgetID = GAD_DONE;
				gadDONE = gadList = CreateGadget( BUTTON_KIND, gadList, &gadNew,
																			 TAG_END );

				gadNew.ng_LeftEdge		=	11;
				gadNew.ng_TopEdge			=	4 + TBSize;
				gadNew.ng_Width				=	99 + ( w * 8 - 80 );
				gadNew.ng_Height			=	100;
				gadNew.ng_Flags				=	PLACETEXT_ABOVE;
				gadNew.ng_GadgetText = "";
				gadNew.ng_GadgetID = GAD_LISTVIEW;
				gadLISTVIEW = gadList = CreateGadget( LISTVIEW_KIND, gadList, &gadNew,
															GTLV_ShowSelected,	NULL,
															GTLV_Selected, 0,
															GTLV_Labels, LView,
															TAG_END );

				win = OpenWindowTags( NULL,
								WA_Left, 172,
								WA_Top, 28,
								WA_Width, 120 + ( w * 8 - 80 ),
								WA_Height, 139 + TBSize,
								WA_CloseGadget, FALSE,
								WA_DepthGadget, TRUE,
								WA_Gadgets, gadContext,
								WA_DragBar, TRUE,
								WA_Activate, TRUE,
								WA_CustomScreen, screen,
								WA_IDCMP, BUTTONIDCMP | LISTVIEWIDCMP |
													IDCMP_REFRESHWINDOW | IDCMP_CLOSEWINDOW,
								WA_Title, title,
								WA_ScreenTitle, &version[5],
								TAG_DONE, NULL);

				if ( win != NULL )
				{
					/* Update gadgets */
					GT_RefreshWindow( win, NULL );

					Selected = HandleGadgetMessages( win, HM_LISTVIEW );

					CloseWindow( win );
					FreeGadgets( gadContext );
				}
				FreeList( LView );
			}
			UnlockPubScreen( NULL, screen );
		}

		if ( vi != NULL ) FreeVisualInfo( vi );
	}

	if ( GadToolsBase != NULL ) CloseLibrary( GadToolsBase );
	if ( IntuitionBase != NULL ) CloseLibrary( IntuitionBase );

	return Selected;
}

int HandleGadgetMessages( struct Window *win, UBYTE HandlerMode )
{
	struct IntuiMessage *msg;
	struct Gadget *gadget;

	int Selected = 1; //Default to the lists first entry
	UWORD msgClass, Code;
	int GadgetID;

	BOOL terminated = FALSE;

	while ( !terminated )
	{
		/* Wait until something happens */
		Wait ( 1L << win->UserPort->mp_SigBit );

	  while ( ( !terminated ) && ( msg = GT_GetIMsg( win->UserPort ) ) )
		{
  		msgClass = msg->Class;
			Code = msg->Code;
		  gadget = (struct Gadget *)msg->IAddress;

  		GT_ReplyIMsg( msg );

	  	switch ( msgClass )
			{
				case IDCMP_GADGETUP:
  				GadgetID = gadget->GadgetID;

					switch ( HandlerMode )
					{
						case HM_LISTVIEW:
							switch ( GadgetID )
							{
								case GAD_MODIFY:
									terminated = TRUE;
								break;

								case GAD_LISTVIEW:
									Selected = Code + 1;
								break;

								case GAD_DONE:
									Selected = -1;
									terminated = TRUE;
								break;
							}
						break;

						case HM_ENTRY:
							switch ( GadgetID )
							{
								case GAD_CANCEL:
									strcpy( EnteredValue, defValue );
									terminated = TRUE;
								break;

								case GAD_OK:
									strcpy( EnteredValue, GetString( gadENTRY ) );
									terminated = TRUE;
								break;
							}
						break;
					}
				break;

				case IDCMP_RAWKEY:
				break;

				case IDCMP_REFRESHWINDOW:
					/* Required by GadTools */
					GT_BeginRefresh( win );
					GT_EndRefresh( win, TRUE );
  			break;

				case IDCMP_CLOSEWINDOW:
					terminated = TRUE;
 				break;

			}/* switch ( msgClass ) */
		}/* while ( !terminated && GetMsg ) */
	}/* while ( !terminated ) */

	return Selected;
}

struct lv_Node *NewLVNode( struct List *list, char *name )
{
	struct lv_Node *lvnode = NULL;

	/* Allocate memory for a new Node structure */
	if ( lvnode = AllocMem( sizeof( struct lv_Node ), MEMF_CLEAR ) )
	{
		/* Set the Node name, type and priority */
		lvnode->nn_Node.ln_Name = lvnode->Info;
		strcpy( lvnode->Info, name );
		lvnode->nn_Node.ln_Type = LVNODE_ID;
		lvnode->nn_Node.ln_Pri = 0;

		/* Add the new Node to the end of the list */
		AddTail( list, (struct Node *)lvnode );
	}

	return lvnode;
}

void FreeList( struct List *list )
{
	struct lv_Node *worknode, *nextnode;

	if ( list != NULL )
	{
		worknode = (struct lv_Node *)( list->lh_Head );

		while ( nextnode = (struct lv_Node *)( worknode->nn_Node.ln_Succ ) )
		{
			FreeMem( worknode, sizeof( struct lv_Node ) );
			worknode = nextnode;
		}

		FreeMem( list, sizeof( struct List ) );
	}
}

string DialogBox( string *sp, string def )
{
	string *t = sp;

	struct Screen *screen;
	struct Window *win;

	void *vi = NULL;

	struct Gadget *gadContext = NULL;
	struct Gadget *gadList = NULL;
	struct Gadget *gadOK, *gadCANCEL, *gadTEXT;
	struct NewGadget gadNew;

	struct TextAttr Topaz80 = { "topaz.font", 8, 0, 0 };

	int TBSize;

	/* Store original value in case of user cancel */
	strcpy( defValue, def );

	IntuitionBase = OpenLibrary( "intuition.library", 37 );
	GadToolsBase = OpenLibrary( "gadtools.library", 37 );

	if ( IntuitionBase != NULL && GadToolsBase != NULL )
	{
		screen = LockPubScreen( NULL );

		if ( screen != NULL )
		{
			TBSize = screen->WBorTop + screen->Font->ta_YSize + 1;
			vi = GetVisualInfo( screen, TAG_END );

			{
				gadList = CreateContext( &gadContext );

				gadNew.ng_LeftEdge		=	11;
				gadNew.ng_TopEdge			=	125 + TBSize;
				gadNew.ng_Width				=	69;
				gadNew.ng_Height			=	14;
				gadNew.ng_GadgetText = "Ok";
				gadNew.ng_TextAttr		=	&Topaz80;
				gadNew.ng_VisualInfo	=	vi;
				gadNew.ng_Flags				=	PLACETEXT_IN;
				gadNew.ng_GadgetID = GAD_OK;
				gadOK = gadList = CreateGadget( BUTTON_KIND, gadList, &gadNew,
																	 TAG_END );

				gadNew.ng_LeftEdge		=	270;
				gadNew.ng_GadgetText = "Cancel";
				gadNew.ng_GadgetID = GAD_CANCEL;
				gadCANCEL = gadList = CreateGadget( BUTTON_KIND, gadList, &gadNew,
																	 TAG_END );

				gadNew.ng_LeftEdge		=	74;
				gadNew.ng_TopEdge			=	105 + TBSize;
				gadNew.ng_Width				=	205;
				gadNew.ng_Height			=	14;
				gadNew.ng_Flags				=	PLACETEXT_ABOVE;
				gadNew.ng_GadgetText = "";
				gadNew.ng_GadgetID = GAD_ENTRY;
				gadENTRY = gadList = CreateGadget( STRING_KIND, gadList, &gadNew,
															GTST_String, def,
															GTST_MaxChars, 30,
															TAG_END );

				/* Display the entry text */
				gadNew.ng_LeftEdge		=	17;
				gadNew.ng_TopEdge			=	1 + TBSize;
				gadNew.ng_Width				=	356;
				gadNew.ng_Height			=	11;
				gadNew.ng_GadgetText = "";
				gadNew.ng_GadgetID = GAD_TEXT;

				while ( *t != NULL )
				{
					gadTEXT = gadList = CreateGadget( TEXT_KIND, gadList, &gadNew,
																	GTTX_Text, *(t++),
																	TAG_END );

					gadNew.ng_TopEdge += 12;
				}

				win = OpenWindowTags( NULL,
								WA_Left, 172,
								WA_Top, 28,
								WA_Width, 350,
								WA_Height, 146 + TBSize,
								WA_CloseGadget, FALSE,
								WA_DepthGadget, TRUE,
								WA_Gadgets, gadContext,
								WA_DragBar, TRUE,
								WA_Activate, TRUE,
								WA_CustomScreen, screen,
								WA_IDCMP, BUTTONIDCMP | IDCMP_REFRESHWINDOW |
													IDCMP_CLOSEWINDOW,
								WA_Title, "Enter new values",
								WA_ScreenTitle, &version[5],
								TAG_DONE, NULL);

				if ( win != NULL )
				{
					/* Update gadgets */
					GT_RefreshWindow( win, NULL );

					HandleGadgetMessages( win, HM_ENTRY );

					CloseWindow( win );
					FreeGadgets( gadContext );
				}
			}
			UnlockPubScreen( NULL, screen );
		}

		if ( vi != NULL ) FreeVisualInfo( vi );
	}

	if ( GadToolsBase != NULL ) CloseLibrary( GadToolsBase );
	if ( IntuitionBase != NULL ) CloseLibrary( IntuitionBase );

	return EnteredValue;
}
