/*
** GUI Functions
*/

#include "config.h"

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

#include <proto/dos.h>
#include <proto/icon.h>
#include <libraries/gadtools.h>

#include "mui.h"
#include <MUI/Lamp_mcc.h>
#include <MUI/NListview_mcc.h>
#include <MUI/busy_mcc.h>

#include "gui.h"
#include "pix/amsterlogo.h"
#include "pix/infowinicon.h"
#include "pix/msgwinicon.h"
#include "pix/chatwinicon.h"
#include "napster.h"
#include "download.h"
#include "prefs.h"
#include "info.h"
#include "msg.h"
#include "search.h"
#include "amster_Cat.h"

struct Library *MUIMasterBase=0;
struct guidata mygui;
struct guidata *gui = &mygui;
int gui_napon=0;

void prf_save(void);
void gui_free(void);
int gui_setup(void);
MUIF gui_handle(REG(a0) struct Hook *h,REG(a2) Object *app, REG(a1) u_long *id);
MUIF dl_dispatch(REG(a0) struct IClass *cl,REG(a2) Object *obj,REG(a1) Msg msg);
MUIF rexx_dispatch(REG(a0) struct Hook *h, REG(a2) Object *app, REG(a1) struct RexxMsg *rm);
void gui_connect(void);
void gui_about(void);
void gui_appicon(int t);

struct Hook handleHook = {{0,0}, &gui_handle, NULL, NULL};


void gui_run(unsigned long tcpsig)
{
	ULONG sigs=0;

	memset(gui,0,sizeof(struct guidata));
	if (gui_setup()) {
		while(DoMethod(gui->app,MUIM_Application_NewInput,&sigs) != MUIV_Application_ReturnID_Quit) {
			if (sigs) {
				sigs = Wait(sigs|SIGBREAKF_CTRL_C|tcpsig);
				if (sigs&SIGBREAKF_CTRL_C)
					break;
				if (sigs&tcpsig) {
					if(nap_listen()) gui_napon=0;
				}
			}
		}
		if(gui_napon) nap_logout();
	}
	gui_free();
}


void gui_free(void)
{
	gui_appicon(-1);
	if(gui->app) MUI_DisposeObject(gui->app);
	if(gui->redlamp) MUI_DisposeObject(gui->redlamp);
	if(gui->greenlamp) MUI_DisposeObject(gui->greenlamp);
	if(gui->yellowlamp) MUI_DisposeObject(gui->yellowlamp);
	if(gui->msg_mcc) MUI_DeleteCustomClass(gui->msg_mcc);
	if(gui->info_mcc) MUI_DeleteCustomClass(gui->info_mcc);
	if(gui->prf_mcc) MUI_DeleteCustomClass(gui->prf_mcc);
	if(gui->dl_mcc) MUI_DeleteCustomClass(gui->dl_mcc);
	if(gui->search_mcc) MUI_DeleteCustomClass(gui->search_mcc);
	if(MUIMasterBase!=0) CloseLibrary(MUIMasterBase);
}


int gui_setup(void)
{
	static struct Hook rexxHook = { {0,0}, &rexx_dispatch, NULL, NULL };
	Object *logo;

	localize_array(nap_linktype);

	MUIMasterBase = OpenLibrary(MUIMASTER_NAME,MUIMASTER_VMIN);
	if (!MUIMasterBase) {
		printf(MSG_NO_LIBRARY,MUIMASTER_NAME,MUIMASTER_VMIN);
		return(0);
	}

	gui->search_mcc = MUI_CreateCustomClass(NULL,MUIC_Group,NULL,sizeof(struct searchdata),search_dispatch);
	if(!gui->search_mcc) return(-1);

	gui->dl_mcc = MUI_CreateCustomClass(NULL,MUIC_Window,NULL,sizeof(struct dl_data),dl_dispatch);
	if (!gui->dl_mcc) return(-1);

	gui->prf_mcc = MUI_CreateCustomClass(NULL,MUIC_Window,NULL,sizeof(struct prfdata),prf_dispatch);
	if (!gui->prf_mcc) return(-1);

	gui->info_mcc = MUI_CreateCustomClass(NULL,MUIC_Window,NULL,sizeof(struct infodata),info_dispatch);
	if (!gui->info_mcc) return(-1);

	gui->msg_mcc = MUI_CreateCustomClass(NULL,MUIC_Window,NULL,sizeof(struct msgdata),msg_dispatch);
	if (!gui->msg_mcc) return(-1);

	gui->redlamp = LampObject,
		MUIA_Lamp_Type, MUIV_Lamp_Type_Big,
		MUIA_Lamp_Red, 0xffffffff,
		MUIA_Lamp_Green, 0x00000000,
		MUIA_Lamp_Blue, 0x00000000,
	End;
	gui->greenlamp = LampObject,
		MUIA_Lamp_Type, MUIV_Lamp_Type_Big,
		MUIA_Lamp_Red, 0x00000000,
		MUIA_Lamp_Green, 0xffffffff,
		MUIA_Lamp_Blue, 0x00000000,
	End;
	gui->yellowlamp = LampObject,
		MUIA_Lamp_Type, MUIV_Lamp_Type_Big,
		MUIA_Lamp_Red, 0xffffffff,
		MUIA_Lamp_Green, 0xffffffff,
		MUIA_Lamp_Blue, 0x00000000,
	End;
	if(!gui->redlamp || !gui->greenlamp || !gui->yellowlamp) {
		printf("Cannot create lamp objects!\n");
		return(0);
	}

	gui->app = ApplicationObject,
		MUIA_Application_Title, "Amster",
		MUIA_Application_Version, "$VER: Amster "AMSTER_VERSION" ("AMSTER_DATE")",
		MUIA_Application_Description, MSG_CX_DESCRIPTION,
		MUIA_Application_Base, "AMSTER",
		MUIA_Application_RexxHook, &rexxHook,
		MUIA_Application_HelpFile, "PROGDIR:Amster.guide",
		MUIA_Application_Menustrip, MenustripObject,
			Child, MenuObject,
				MUIA_Menu_Title, MSG_PROJECT_MENU,
				Child, gui->aboutmenu = MenuitemObject,
					MUIA_Menuitem_Title, TOMENUTEXT(MSG_PROJECT_ABOUT),
					MUIA_Menuitem_Shortcut, MSG_PROJECT_ABOUT,
				End,
				Child, gui->muimenu = MenuitemObject,
					MUIA_Menuitem_Title, MSG_PROJECT_ABOUTMUI,
				End,
				Child, gui->hidemenu = MenuitemObject,
					MUIA_Menuitem_Title, TOMENUTEXT(MSG_PROJECT_HIDE),
					MUIA_Menuitem_Shortcut, MSG_PROJECT_HIDE,
				End,
				Child, MenuitemObject,
					MUIA_Menuitem_Title, NM_BARLABEL,
				End,
				Child, gui->quitmenu = MenuitemObject,
					MUIA_Menuitem_Title, TOMENUTEXT(MSG_PROJECT_QUIT),
					MUIA_Menuitem_Shortcut, MSG_PROJECT_QUIT,
				End,
			End,
			Child, MenuObject,
				MUIA_Menu_Title, MSG_SETTINGS_MENU,
				Child, gui->amstersetmenu = MenuitemObject,
					MUIA_Menuitem_Title, MSG_SETTINGS_CONFIG,
				End,
				Child, gui->muisetmenu = MenuitemObject,
					MUIA_Menuitem_Title, MSG_SETTINGS_MUI,
				End,
			End,
		End,


		SubWindow, gui->swin = NewObject(gui->prf_mcc->mcc_Class,NULL,TAG_DONE),


		SubWindow, gui->iwin = NewObject(gui->info_mcc->mcc_Class,NULL,TAG_DONE),


		SubWindow, gui->mwin = NewObject(gui->msg_mcc->mcc_Class,NULL,TAG_DONE),

/*
		SubWindow, gui->bwin = WindowObject,
		MUIA_Window_Title, "Connecting...",
		MUIA_Window_ID   , MAKE_ID('B','U','S','Y'),

		WindowContents, VGroup,
			Child, BusyObject,
				MUIA_Busy_Speed, MUIV_Busy_Speed_User,
				End,
			End,
		End,
*/

		SubWindow, gui->win = WindowObject,
		MUIA_Window_ID, MAKE_ID('M','A','I','N'),
		MUIA_Window_Title, "Amster v"AMSTER_VERSION,
		WindowContents, VGroup,
			Child, HGroup,
				Child, logo = BodychunkObject,
					TextFrame,
					MUIA_Background, MUII_BACKGROUND,
					MUIA_FixWidth, AMSTERLOGO_WIDTH,
					MUIA_FixHeight, AMSTERLOGO_HEIGHT,
					MUIA_Bitmap_Width, AMSTERLOGO_WIDTH,
					MUIA_Bitmap_Height, AMSTERLOGO_HEIGHT,
					MUIA_Bodychunk_Depth, AMSTERLOGO_DEPTH,
					MUIA_Bodychunk_Body, (ULONG *)AMSTERLOGO_BODY,
					MUIA_Bodychunk_Compression, AMSTERLOGO_COMPRESSION,
					MUIA_Bodychunk_Masking, AMSTERLOGO_MASKING,
					MUIA_Bitmap_SourceColors, (ULONG *)AMSTERLOGO_COLORS,
					MUIA_InputMode, MUIV_InputMode_Immediate,
					MUIA_ShowSelState, FALSE,
				End,
				Child, HSpace(0),
				Child, gui->infoicon = BodychunkObject,
					ImageButtonFrame,
					MUIA_Background, MUII_ButtonBack,
					MUIA_FixWidth, INFOWINICON_WIDTH,
					MUIA_FixHeight, INFOWINICON_HEIGHT,
					MUIA_Bitmap_Width, INFOWINICON_WIDTH,
					MUIA_Bitmap_Height, INFOWINICON_HEIGHT,
					MUIA_Bodychunk_Depth, INFOWINICON_DEPTH,
					MUIA_Bodychunk_Body, (ULONG *)INFOWINICON_BODY,
					MUIA_Bodychunk_Compression, INFOWINICON_COMPRESSION,
					MUIA_Bodychunk_Masking, INFOWINICON_MASKING,
					MUIA_Bitmap_SourceColors, (ULONG *)INFOWINICON_COLORS,
					MUIA_Bitmap_Transparent, 0,
					MUIA_InputMode, MUIV_InputMode_RelVerify,
				End,
				Child, HSpace(0),
				Child, gui->msgicon = BodychunkObject,
					ImageButtonFrame,
					MUIA_Background, MUII_ButtonBack,
					MUIA_FixWidth, MSGWINICON_WIDTH,
					MUIA_FixHeight, MSGWINICON_HEIGHT,
					MUIA_Bitmap_Width, MSGWINICON_WIDTH,
					MUIA_Bitmap_Height, MSGWINICON_HEIGHT,
					MUIA_Bodychunk_Depth, MSGWINICON_DEPTH,
					MUIA_Bodychunk_Body, (ULONG *)MSGWINICON_BODY,
					MUIA_Bodychunk_Compression, MSGWINICON_COMPRESSION,
					MUIA_Bodychunk_Masking, MSGWINICON_MASKING,
					MUIA_Bitmap_SourceColors, (ULONG *)MSGWINICON_COLORS,
					MUIA_Bitmap_Transparent, 0,
					MUIA_InputMode, MUIV_InputMode_RelVerify,
				End,
				Child, HSpace(0),
				Child, gui->chaticon = BodychunkObject,
					ImageButtonFrame,
					MUIA_Background, MUII_ButtonBack,
					MUIA_FixWidth, CHATWINICON_WIDTH,
					MUIA_FixHeight, CHATWINICON_HEIGHT,
					MUIA_Bitmap_Width, CHATWINICON_WIDTH,
					MUIA_Bitmap_Height, CHATWINICON_HEIGHT,
					MUIA_Bodychunk_Depth, CHATWINICON_DEPTH,
					MUIA_Bodychunk_Body, (ULONG *)CHATWINICON_BODY,
					MUIA_Bodychunk_Compression, CHATWINICON_COMPRESSION,
					MUIA_Bodychunk_Masking, CHATWINICON_MASKING,
					MUIA_Bitmap_SourceColors, (ULONG *)CHATWINICON_COLORS,
					MUIA_Bitmap_Transparent, 0,
					MUIA_InputMode, MUIV_InputMode_RelVerify,
					MUIA_Disabled, TRUE,
				End,
				Child, HSpace(0),
			End,
			Child, HGroup,
				Child, gui->inbut = SimpleButton(MSG_CONNECT_GAD),
				Child, gui->outbut = SimpleButton(MSG_DISCONNECT_GAD),
				Child, gui->rebut = SimpleButton(MSG_RECONNECT_GAD),
				Child, gui->setbut = SimpleButton(MSG_SETTINGS_GAD),
			End,
			Child, RectangleObject,
				MUIA_FixHeight, 8,
				MUIA_Rectangle_HBar, TRUE,
			End,
			Child, gui->searchpanel = NewObject(gui->search_mcc->mcc_Class,NULL,TAG_DONE),
			Child, RectangleObject,
				MUIA_FixHeight, 8,
				MUIA_Rectangle_HBar, TRUE,
			End,
			Child, HGroup,
				Child, gui->stat = TextObject,
					TextFrame,
					MUIA_Background, MUII_TextBack,
					MUIA_Text_PreParse, "\33c",
				End,
				Child, gui->lamp = LampObject,
					MUIA_Lamp_Type, MUIV_Lamp_Type_Huge,
					MUIA_Lamp_Color, MUIV_Lamp_Color_Off,
				End,
			End,
		End,
		End,

	End;

	if (!gui->app) {
		printf(MSG_APP_ERROR);
		return(0);
	}

	DoMethod(logo,MUIM_Notify,MUIA_Selected,TRUE,gui->app,3,MUIM_CallHook,&handleHook,15);
	DoMethod(logo,MUIM_Notify,MUIA_Selected,TRUE,logo,3,MUIM_Set,MUIA_Selected,FALSE);

	DoMethod(gui->infoicon,MUIM_Notify,MUIA_Pressed,FALSE,gui->iwin,1,INFO_OPEN);
	DoMethod(gui->msgicon,MUIM_Notify,MUIA_Pressed,FALSE,gui->mwin,1,MSG_OPEN);

	DoMethod(gui->inbut,MUIM_Notify,MUIA_Pressed,FALSE,gui->app,3,MUIM_CallHook,&handleHook,0);
	DoMethod(gui->outbut,MUIM_Notify,MUIA_Pressed,FALSE,gui->app,3,MUIM_CallHook,&handleHook,1);
	DoMethod(gui->rebut,MUIM_Notify,MUIA_Pressed,FALSE,gui->app,3,MUIM_CallHook,&handleHook,2);
	DoMethod(gui->setbut,MUIM_Notify,MUIA_Pressed,FALSE,gui->swin,1,PRF_OPEN);

	DoMethod(gui->aboutmenu,MUIM_Notify,MUIA_Menuitem_Trigger,MUIV_EveryTime,gui->app,3,MUIM_CallHook,&handleHook,15);
	DoMethod(gui->muimenu,MUIM_Notify,MUIA_Menuitem_Trigger,MUIV_EveryTime,gui->app,2,MUIM_Application_AboutMUI,gui->win);
	DoMethod(gui->muisetmenu,MUIM_Notify,MUIA_Menuitem_Trigger,MUIV_EveryTime,gui->app,2,MUIM_Application_OpenConfigWindow,0);
	DoMethod(gui->amstersetmenu,MUIM_Notify,MUIA_Menuitem_Trigger,MUIV_EveryTime,gui->swin,1,PRF_OPEN);
	DoMethod(gui->hidemenu,MUIM_Notify,MUIA_Menuitem_Trigger,MUIV_EveryTime,gui->app,3,MUIM_Set,MUIA_Application_Iconified,TRUE);
	DoMethod(gui->quitmenu,MUIM_Notify,MUIA_Menuitem_Trigger,MUIV_EveryTime,gui->app,2,MUIM_Application_ReturnID,MUIV_Application_ReturnID_Quit);
	DoMethod(gui->win,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,gui->app,2,MUIM_Application_ReturnID,MUIV_Application_ReturnID_Quit);

	gui_appicon(0);

	gui_state(0);

	set(gui->win,MUIA_Window_Open,TRUE);

	if(pref_autocon) gui_connect();
	else set(gui->stat,MUIA_Text_Contents,MSG_STATUS2_NOTCONNECTED);

	return(1);
}


MUIF gui_handle(REG(a0) struct Hook *h,REG(a2) Object *app, REG(a1) u_long *id)
{
	switch(*id) {
		case 0:
			gui_connect();
			break;
		case 1:
			if(gui_napon) nap_logout();
			gui_napon=0;
			set(gui->stat,MUIA_Text_Contents,MSG_STATUS2_NOTCONNECTED);
			break;
		case 2:
			if(gui_napon) nap_logout();
			set(gui->inbut,MUIA_Disabled,TRUE);
			set(gui->lamp,MUIA_Lamp_Color,MUIV_Lamp_Color_Connecting);
			set(gui->stat,MUIA_Text_Contents,MSG_STATUS2_CONNECTING);
			if(nap_login()) gui_napon=1; else gui_state(0);
			break;
		case 15:
			MUI_Request(app, gui->win, 0L, (char *)MSG_ABOUT_TITLE, (char *)MSG_OK_GAD, (char *)MSG_ABOUT, AMSTER_VERSION, AMSTER_DATE);
			break;
		case 99:
			if (dl_flush() && !gui_napon) nap_logout();
			break;
	}
	return(0);
}


void gui_state(int s)
{
	switch(s) {
		case 0:
			set(gui->inbut,MUIA_Disabled,FALSE);
			set(gui->outbut,MUIA_Disabled,TRUE);
			set(gui->rebut,MUIA_Disabled,TRUE);
			set(gui->lamp,MUIA_Lamp_Color,MUIV_Lamp_Color_Off);
			DoMethod(gui->searchpanel,SEARCH_CLEAR,1);
			gui_appicon(2);
			break;
		case 1:
			set(gui->inbut,MUIA_Disabled,TRUE);
			set(gui->outbut,MUIA_Disabled,FALSE);
			set(gui->rebut,MUIA_Disabled,FALSE);
			set(gui->lamp,MUIA_Lamp_Color,MUIV_Lamp_Color_Ok);
			gui_appicon(1);
			break;
	}
}


void gui_srvstat(int a, int b, int c)
{
	static char buf[100];
	sprintf(buf,MSG_STATUS2_SONGSONLINE,b,a,c);
	set(gui->stat,MUIA_Text_Contents,buf);
}


void gui_connect(void)
{
	if(gui_napon) return;
	/* The busy indicator doesn't move while connecting, which kinda was the
	   idea. So this problem remains to be solved. */
	/*set(gui->bwin,MUIA_Window_Open,TRUE);*/
	set(gui->inbut,MUIA_Disabled,TRUE);
	set(gui->lamp,MUIA_Lamp_Color,MUIV_Lamp_Color_Connecting);
	set(gui->stat,MUIA_Text_Contents,MSG_STATUS2_CONNECTING);
	if(nap_login()) gui_napon=1; else gui_state(0);
	/*set(gui->bwin,MUIA_Window_Open,FALSE);*/
}


void gui_found(songdata song)
{
	DoMethod(gui->searchpanel,SEARCH_FOUND,song);
}


void localize_array(char *array[])
{
	char **x;

	for(x=array;*x;x++)
		*x = (char *)((struct FC_String *)(*x))->msg;
}


void gui_appicon(int t)
{
	static struct DiskObject *on, *off;

	switch(t) {
		case 0:
			on = GetDiskObject("PROGDIR:icons/amster_online");
			off = GetDiskObject("PROGDIR:icons/amster_offline");
			break;

		case -1:
			if(on) FreeDiskObject(on);
			if(off) FreeDiskObject(off);
			break;

		case 1:
			if(on) set(gui->app,MUIA_Application_DiskObject,on);
			break;

		case 2:
			if(off) set(gui->app,MUIA_Application_DiskObject,off);
			break;

	}
}
