/*  Copyright (C) 2002 Tom Parker (tom@carrott.org),
                       Matthias Münch (matthias@amigaworld.de)

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    In addition, as a special exception, Tom Parker and Matthias Münch give
    permission to link the code of this program with a TCP stack of your 
    choice, any official MUI libraries or classes and any custom MUI classes
    that should be necessary for the operation of this program.  This 
    exception also gives you permission to distribute linked combinations 
    including this software with any of the before-mentioned libraries and 
    classes.  You must obey the GNU General Public License in all respects for
    all of the code used other than that provided by the before-mentioned 
    libraries and classes.  As part of this exception you are obliged to 
    follow the license terms of the before-mentioned libraries, this license
    does not compel you to follow those terms, but if you do not then you may
    not link with those libraries.  If you modify this file, you may extend
    this exception to your version of the file, but you are not obligated to
    do so.  If you do not wish to do so, delete this exception statement from
    your version.
*/
/*
** GUI setup, main input loop
*/

#include "common.h"

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

#include <proto/icon.h>

#include <MUI/NListview_mcc.h>
#include <MUI/TextEditor_mcc.h>

#include "url.h"
#include "edit.h"
#include "madthread.h"

extern struct MUI_Command rexx_cmds[];

static muiclass klaslarim[] = {
	{ MUIC_NList, sizeof(struct rosterdata), &roster_dispatch, &gui.roster_mcc },
/*	{ MUIC_Text, sizeof(struct urldata), &url_dispatch, &gui.url_mcc }, */
	{ MUIC_Textinput, sizeof(struct editdata), &edit_dispatch, &gui.edit_mcc },
	{ MUIC_NListview, sizeof(struct chatareadata), &chatarea_dispatch, &gui.chatarea_mcc },
	{ MUIC_Group, sizeof(struct xmlformdata), &xmlform_dispatch, &gui.xmlform_mcc },
	{ MUIC_Window, sizeof(struct chatdata), &chat_dispatch, &gui.chat_mcc },
	{ MUIC_Window, sizeof(struct gchatdata), &gchat_dispatch, &gui.gchat_mcc },
	{ MUIC_Window, sizeof(struct contactdata), &contact_dispatch, &gui.contact_mcc },
	{ MUIC_Window, sizeof(struct logindata), &login_dispatch, &gui.login_mcc },
	{ MUIC_Window, 0, &about_dispatch, &gui.about_mcc },
	{ MUIC_Window, sizeof(struct condata), &console_dispatch, &gui.console_mcc },
	{ MUIC_Window, sizeof(struct writedata), &write_dispatch, &gui.write_mcc },
	{ MUIC_Window, sizeof(struct readdata), &read_dispatch, &gui.read_mcc },
	{ MUIC_Window, sizeof(struct userinfodata), &userinfo_dispatch, &gui.userinfo_mcc },
	{ MUIC_Window, sizeof(struct agentsdata), &agents_dispatch, &gui.agents_mcc },
	{ MUIC_Window, sizeof(struct registerdata), &register_dispatch, &gui.register_mcc },
	{ MUIC_Window, sizeof(struct prefsdata), &prefs_dispatch, &gui.prefs_mcc },
	{ MUIC_Window, 0, &presence_dispatch, &gui.presence_mcc },
	{ MUIC_Window, 0, &xfer_dispatch, &gui.xfer_mcc },
	{ MUIC_Window, sizeof(struct xferreqdata), &xfer_req_dispatch, &gui.xfer_req_mcc },
	{ MUIC_Window, sizeof(struct searchdata), &search_dispatch, &gui.search_mcc },
	{ MUIC_Window, sizeof(struct searchresultdata), &search_result_dispatch, &gui.search_result_mcc },

	{ NULL, 0, NULL, NULL }
};

struct Library *MUIMasterBase = NULL;
struct guidata gui;

static void gui_free(void);
static int gui_setup(void);
MUI_HOOK_DECL(gui_handle, Object *app, u_long *id);
static void gui_appicon(int op);


void gui_run(void)
{
	u_long 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 | net.sigmask | mt_sigmask);
				if(sigs & SIGBREAKF_CTRL_C) break;
				if(sigs & net.sigmask) net_listen();
				if(sigs & mt_sigmask) mt_listen();
			}
		}
	}
	if(net.state != NET_OFF) net_disconnect(NULL);
	http_down();
	gui_free();
}


static void gui_free(void)
{
	if(gui.app) MUI_DisposeObject(gui.app);
	gui_appicon(-1);
	mui_classes_cleanup(klaslarim);
	if(MUIMasterBase) CloseLibrary(MUIMasterBase);
}


static int gui_setup(void)
{
	static const char *lala[] =
	{
		(char *)_MSG_PRES_ONLINE,
		(char *)_MSG_PRES_CHAT,
		(char *)_MSG_PRES_AWAY,
		(char *)_MSG_PRES_XA,
		(char *)_MSG_PRES_DND,
		NULL
	};
	static const char *bibi[] =
	{
		(char *)_MSG_ROSTER_TAB,
		(char *)_MSG_PRESENCE_TAB,
		NULL
	};
	static struct Hook handleHook = {{0,0}, &gui_handle, NULL, NULL};
	Object *connmenu, *aboutmenu, *muimenu, *helpmenu, *hidemenu, *quitmenu;
	Object *addmenu, *readmenu, *writemenu, *chatmenu, *infomenu, *sendmenu, *acceptmenu, *subsmenu, *remmenu;
	Object *presmenu, *conmenu, *agentsmenu, *gchatmenu, *xfermenu;
	Object *muiprfmenu, *prfmenu, *lastsavedmenu, *saveallmenu;
	Object *slider;

	MUIMasterBase = OpenLibrary(MUIMASTER_NAME, MUIMASTER_VMIN);
	if(!MUIMasterBase)
	{
		printf("Cannot open %s %d!", MUIMASTER_NAME, MUIMASTER_VMIN);
		return 0;
	}
	if(!mui_classes_setup(klaslarim)) return(0);

	localize_array(lala);
	localize_array(bibi);

	gui.app = ApplicationObject,
		MUIA_Application_Title, "Jabberwocky",
		MUIA_Application_Version, about_version_mui(),
		MUIA_Application_Description, MSG_CX_DESCRIPTION,
		MUIA_Application_Base, "JABBERWOCKY",
		MUIA_Application_Commands, &rexx_cmds,
		MUIA_Application_HelpFile, JABBERWOCKY_HELP,

		MUIA_Application_Menustrip, MenustripObject,
			Child, MenuObject,
				MUIA_Menu_Title, MSG_MENU_JABBERWOCKY,
				Child, connmenu = (void *)mui_menu(MSG_MENU_ACCOUNT),
				Child, mui_menu(NULL),
				Child, aboutmenu = mui_menu(MSG_MENU_ABOUT),
				Child, muimenu = mui_menu(MSG_MENU_ABOUTMUI),
				Child, helpmenu = mui_menu(MSG_MENU_HELP),
				Child, mui_menu(NULL),
				Child, hidemenu = mui_menu(MSG_MENU_HIDE),
				Child, quitmenu = mui_menu(MSG_MENU_QUIT),
			End,
			Child, MenuObject,
				MUIA_Menu_Title, MSG_MENU_ROSTER,
				Child, addmenu = mui_menu("Add Contact..."),
				Child, readmenu = mui_menu("Read Message"),
				Child, writemenu = mui_menu("Write Message"),
				Child, chatmenu = mui_menu("Chat"),
				Child, infomenu = mui_menu("Information"),
				Child, sendmenu = mui_menu("Send File"),
				Child, subsmenu = mui_menu("Subscribe"),
				Child, acceptmenu = mui_menu("Accept Subscription"),
				Child, remmenu = mui_menu("Remove Contact"),
			End,
			Child, MenuObject,
				MUIA_Menu_Title, MSG_MENU_WINDOWS,
				Child, conmenu = mui_menu("Console"),
				Child, presmenu = mui_menu("Subscriptions"),
				Child, agentsmenu = mui_menu("Agents List"),
				Child, xfermenu = mui_menu("File Transfers"),
				Child, gchatmenu = mui_menu("New Conference"),
			End,
			Child, MenuObject,
				MUIA_Menu_Title, MSG_MENU_SETTINGS,
				Child, mui_tmenu("Show Online Users"),
				Child, mui_tmenu("Popup Notify"),
				Child, mui_tmenu("Sound Notify"),
				Child, mui_menu(NULL),
				Child, prfmenu = mui_menu(MSG_MENU_PREFS),
				Child, muiprfmenu = mui_menu(MSG_MENU_MUIPREFS),
				Child, mui_menu(NULL),
				Child, lastsavedmenu = mui_menu(MSG_MENU_LASTSAVED),
				Child, saveallmenu = mui_menu(MSG_MENU_SAVESETTINGS),
			End,
			Child, MenuObject,
				MUIA_Menu_Title, MSG_MENU_AREXX,
				Child, mui_menu(MSG_MENU_EXECUTE),
				Child, mui_menu(NULL),
			End,
		End,

		SubWindow, gui.win = WindowObject,
		MUIA_Window_ID, MAKE_ID('M','A','I','N'),
		MUIA_Window_Title, "Jabberwocky",
		WindowContents, VGroup,
			Child, gui.info = TextObject,
				TextFrame,
				MUIA_Background, MUII_TextBack,
				MUIA_Text_PreParse, "\33c",
				MUIA_Text_Contents, MSG_WELCOME,
			End,
			Child, RegisterGroup(bibi),
				Child, NListviewObject,
					MUIA_NListview_NList, gui.list = NewObject(gui.roster_mcc->mcc_Class,NULL,TAG_DONE),
				End,
				Child, VGroup,
					Child, gui.preslist = CycleObject,
						MUIA_Cycle_Entries, lala,
						MUIA_CycleChain, 1,
					End,
					Child, gui.presinfo = TextObject,
						MUIA_Text_Contents, "Note",
					End,
					Child, HGroup,
						MUIA_Group_HorizSpacing, 0,
						Child, gui.pres = TextEditorObject,
							MUIA_FixHeightTxt, "\n\n\n\n",
							MUIA_CycleChain, 1,
						End,
						Child, slider = ScrollbarObject, End,
					End,
					Child, VSpace(0),
				End,
			End,
			Child, HGroup,
				Child, gui.conbut = mui_button(MSG_CONNECT_GAD),
				Child, gui.disbut = mui_button(MSG_DISCONNECT_GAD),
			End,
		End,
		End,

		SubWindow, gui.conwin = NewObject(gui.console_mcc->mcc_Class,NULL,TAG_DONE),
		SubWindow, gui.logwin = NewObject(gui.login_mcc->mcc_Class,NULL,TAG_DONE),
		SubWindow, gui.aboutwin = NewObject(gui.about_mcc->mcc_Class,NULL,TAG_DONE),
		SubWindow, gui.agentswin = NewObject(gui.agents_mcc->mcc_Class,NULL,TAG_DONE),
		SubWindow, gui.prfwin = NewObject(gui.prefs_mcc->mcc_Class,NULL,TAG_DONE),
		SubWindow, gui.preswin = NewObject(gui.presence_mcc->mcc_Class,NULL,TAG_DONE),
		SubWindow, gui.xferwin = NewObject(gui.xfer_mcc->mcc_Class,NULL,TAG_DONE),

	End;

	if(!gui.app) {
		printf("Cannot create mui application!");
		return(0);
	}

	set(gui.pres, MUIA_TextEditor_Slider, slider);
	set(gui.disbut, MUIA_Disabled, TRUE);

	DoMethod(gui.conbut, MUIM_Notify, MUIA_Pressed, FALSE, gui.app, 3, MUIM_CallHook, &handleHook, 0);
	DoMethod(gui.disbut, MUIM_Notify, MUIA_Pressed, FALSE, gui.app, 3, MUIM_CallHook, &handleHook, 1);

	DoMethod(gui.preslist, MUIM_Notify, MUIA_Cycle_Active, MUIV_EveryTime, gui.app, 3, MUIM_CallHook, &handleHook, 2);

	DoMethod(connmenu, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime, gui.logwin, 1, LOGIN_OPEN);
	DoMethod(aboutmenu,MUIM_Notify,MUIA_Menuitem_Trigger,MUIV_EveryTime,gui.aboutwin,3,MUIM_Set,MUIA_Window_Open,TRUE);
	DoMethod(muimenu,MUIM_Notify,MUIA_Menuitem_Trigger,MUIV_EveryTime,gui.app,2,MUIM_Application_AboutMUI,gui.win);
	DoMethod(helpmenu,MUIM_Notify,MUIA_Menuitem_Trigger,MUIV_EveryTime,gui.app,5,MUIM_Application_ShowHelp,gui.win,JABBERWOCKY_HELP,0,0);
	DoMethod(hidemenu,MUIM_Notify,MUIA_Menuitem_Trigger,MUIV_EveryTime,gui.app,3,MUIM_Set,MUIA_Application_Iconified,TRUE);
	DoMethod(quitmenu,MUIM_Notify,MUIA_Menuitem_Trigger,MUIV_EveryTime,gui.app,2,MUIM_Application_ReturnID,MUIV_Application_ReturnID_Quit);

	DoMethod(addmenu, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime, gui.app, 3, MUIM_CallHook, &handleHook, 71);
	DoMethod(readmenu, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime, gui.list, 2, ROSTER_MENU, ROSTER_READ);
	DoMethod(writemenu, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime, gui.app, 3, MUIM_CallHook, &handleHook, 70);
	DoMethod(chatmenu, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime, gui.list, 2, ROSTER_MENU, ROSTER_CHAT);
	DoMethod(infomenu, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime, gui.list, 2, ROSTER_MENU, ROSTER_INFO);
	DoMethod(sendmenu, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime, gui.list, 2, ROSTER_MENU, ROSTER_SEND);
	DoMethod(acceptmenu, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime, gui.list, 2, ROSTER_MENU, ROSTER_ACCEPT);
	DoMethod(subsmenu, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime, gui.list, 2, ROSTER_MENU, ROSTER_SUBS);
	DoMethod(remmenu, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime, gui.list, 2, ROSTER_MENU, ROSTER_REMOVE);

	DoMethod(presmenu, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime, gui.preswin, 3, MUIM_Set, MUIA_Window_Open, TRUE);
	DoMethod(conmenu, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime, gui.conwin, 3, MUIM_Set, MUIA_Window_Open, TRUE);
	DoMethod(agentsmenu, MUIM_Notify, MUIA_Menuitem_Trigger,MUIV_EveryTime, gui.agentswin, 3, MUIM_Set, MUIA_Window_Open, TRUE);
	DoMethod(gchatmenu, MUIM_Notify, MUIA_Menuitem_Trigger,MUIV_EveryTime, gui.app, 3, MUIM_CallHook, &handleHook, 42);
	DoMethod(xfermenu, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime, gui.xferwin, 3, MUIM_Set, MUIA_Window_Open, TRUE);


	DoMethod(prfmenu, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime, gui.prfwin, 1, PREFS_OPEN);
	DoMethod(muiprfmenu, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime, gui.app, 2, MUIM_Application_OpenConfigWindow, 0);
	DoMethod(lastsavedmenu, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime, gui.prfwin, 1, PREFS_LASTSAVED);


	DoMethod(gui.win,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,gui.app,2,MUIM_Application_ReturnID,MUIV_Application_ReturnID_Quit);
	DoMethod(gui.app, MUIM_Notify, MUIA_Application_Iconified, FALSE, gui.app, 3, MUIM_CallHook, &handleHook, 90);


	prf_load_account();

	if(!prf.user || !prf.pass)
		DoMethod(gui.logwin, LOGIN_OPEN);
	else
		set(gui.win, MUIA_Window_Open, TRUE);


	con_debug("Started.");
	prf_event(EVT_STARTUP);

	return 1;
}


MUI_HOOK(gui_handle, Object *app, u_long *id)
{
	iks *x;
	u_long tmp;
	int show = IKS_SHOW_AVAILABLE;
	char *text;

	switch(*id)
	{
	case 0:
		net.regflag = 0;
		net_connect();
		break;

	case 1:
		net_disconnect("Connection closed.");
		break;

	case 2:
		GetAttr(MUIA_Cycle_Active, gui.preslist, &tmp);
		switch(tmp)
		{
		case 1: show = IKS_SHOW_CHAT; break;
		case 2: show = IKS_SHOW_AWAY; break;
		case 3: show = IKS_SHOW_XA; break;
		case 4: show = IKS_SHOW_DND; break;
		}
		text = (char *)DoMethod(gui.pres, MUIM_TextEditor_ExportText);
		x = iks_make_pres(IKS_TYPE_SET, show, NULL, convert_utf8(text));
		if(text) FreeVec(text);
		iks_send(net.parser, x);
		iks_delete(x);
		break;

	case 42:
		gchat_on(NULL);
		break;

	case 70:
		write_to(NULL, NULL, NULL);
		break;

	case 71:
		contact_add();
		break;

	case 90:
		if(net.state == NET_ON) gui_appicon(1); else gui_appicon(0);
		break;
	}

	return 0;
}


void gui_state(char *msg)
{
	static int old_state = NET_OFF;

	if(msg) set(gui.info, MUIA_Text_Contents, (ULONG)msg);

	if(old_state == net.state) return;
	old_state = net.state;

	if(net.state == NET_OFF)
	{
		gui_appicon(0);
		prf_event(EVT_OFFLINE);
		set(gui.conbut, MUIA_Disabled, FALSE);
		set(gui.disbut, MUIA_Disabled, TRUE);
	}
	else
	{
		if(net.state == NET_ON)
		{
			gui_appicon(1);
			prf_event(EVT_ONLINE);
		}
		set(gui.conbut, MUIA_Disabled, TRUE);
		set(gui.disbut, MUIA_Disabled, FALSE);
	}
}


static void gui_appicon(int op)
{
	static struct DiskObject *icon = NULL;

	if(icon) FreeDiskObject(icon);
	icon = NULL;

	switch(op)
	{
		case 0:
			icon = GetDiskObject("PROGDIR:Icons/Jabberwocky_offline");
			break;
		case 1:
			icon = GetDiskObject("PROGDIR:Icons/Jabberwocky_online");
			break;
		case 2:
			icon = GetDiskObject("PROGDIR:Icons/Jabberwocky_event");
			break;
	}

	if(icon) set(gui.app, MUIA_Application_DiskObject, icon);
}
