/*  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.
*/
/*
** common structures, macros, and prototypes
*/

#include "config.h"

#include <sys/types.h>

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

/* #include <proto/iksemel.h> */
#include "iksemel.h"

#include "muihelp.h"
#include "madthread.h"

#include "locale/catalog.h"

#ifndef INCL_COMMON_H
#define INCL_COMMON_H

/*****  Utility Stuff  *****/

typedef struct listitem_s
{
	struct listitem_s *next;
	struct listitem_s *prev;
} listitem;

typedef struct
{
	listitem *first;
	listitem *last;
	int count;
} list;



/*****  Jabber Protocol Stuff  *****/

enum netstates
{
	NET_OFF,
	NET_CONNECT,
	NET_REG,
	NET_AUTH,
	NET_FETCH,
	NET_ON
};

struct netdata
{
	int regflag;
	iksid *id;
	iksparser *parser;
	u_long sigmask;
	enum netstates state;
	char *streamid;
};

extern struct netdata net;


#define MSG_READ 1
#define MSG_CHAT 2

typedef struct
{
	listitem node;
	ikspak *pak;
	int flags;
} jmessage;

enum jusersubs
{
	JUSER_NONE,
	JUSER_TO,
	JUSER_FROM,
	JUSER_BOTH
};

typedef struct
{
	ikspool *p;
	iksid *id;
	char *name;
	enum jusersubs subs;
	enum ikshowtype show;
	char *status;
	Object *infowin;
	Object *chatwin;
	Object *readwin;
	int event;
	list *msgs;
	jmessage *readmsg;
	ikspak *verpak;
	STRPTR error;
	STRPTR ask;
	char rosterstyle[10];
	
} juser_struct, *juser;


typedef struct
{
	ikspool *p;
	char *name, *jid;
	char *url, *desc;
	char *transport, *service;
	int reg, search, chat;
} jagent_struct, *jagent;



/*****  Preferences Stuff  *****/

#define PRF_EVENTS 7

#define EVT_STARTUP 0
#define EVT_EXIT 1
#define EVT_ONLINE 2
#define EVT_OFFLINE 3
#define EVT_MESSAGE 4
#define EVT_CHAT 5
#define EVT_GROUPCHAT 6

#define PRFE_CHANGED 1
#define PRFE_SHOW 2
#define PRFE_WINPOPUP 4
#define PRFE_SCRPOPUP 8

struct prfevent
{
	char *name;
	char *tag;
	int flags;
	char *sound;
	char *cmd;
};

struct preferencesdata
{
	/* startup */
	char *datadir;
	/* account */
	char *user;
	char *pass;
	int savepass;
	/* prefs */
	struct prfevent events[PRF_EVENTS];
	char *charset;
	int http_port;
	int auth_method;
	char *logfile;
	int logflags;
	long options;
};

extern struct preferencesdata prf;




/*****  GUI Stuff  *****/

struct guidata
{
	struct MUI_CustomClass *url_mcc;
	struct MUI_CustomClass *about_mcc;
	struct MUI_CustomClass *panel_mcc;
	struct MUI_CustomClass *roster_mcc;
	struct MUI_CustomClass *login_mcc;
	struct MUI_CustomClass *console_mcc;
	struct MUI_CustomClass *write_mcc;
	struct MUI_CustomClass *msglist_mcc;
	struct MUI_CustomClass *contact_mcc;
	struct MUI_CustomClass *userinfo_mcc;
	struct MUI_CustomClass *chat_mcc;
	Object *app;
	Object *win;
	Object *info,*list,*conbut,*disbut,*panel;
	Object *conwin,*logwin,*aboutwin, *msglistwin;
	struct MUI_CustomClass *edit_mcc;
	Object *pres, *preslist;
	struct MUI_CustomClass *read_mcc;
	struct MUI_CustomClass *agents_mcc;
	Object *agentswin;
	struct MUI_CustomClass *register_mcc;
	struct MUI_CustomClass *gchat_mcc;
	Object *presinfo;
	struct MUI_CustomClass *chatarea_mcc;
	struct MUI_CustomClass *prefs_mcc;
	Object *prfwin;
	struct MUI_CustomClass *presence_mcc;
	Object *preswin;
	struct MUI_CustomClass *xfer_mcc;
	Object *xferwin;
	struct MUI_CustomClass *xfer_req_mcc;
	struct MUI_CustomClass *xmlform_mcc;
	struct MUI_CustomClass *search_mcc;
	struct MUI_CustomClass *search_result_mcc;
};

extern struct guidata gui;


/*****  Class Dispatchers  *****/

MUI_DISPATCH_DECL(roster_dispatch);
MUI_DISPATCH_DECL(console_dispatch);
MUI_DISPATCH_DECL(login_dispatch);
MUI_DISPATCH_DECL(about_dispatch);
MUI_DISPATCH_DECL(write_dispatch);
MUI_DISPATCH_DECL(msglist_dispatch);
MUI_DISPATCH_DECL(contact_dispatch);
MUI_DISPATCH_DECL(userinfo_dispatch);
MUI_DISPATCH_DECL(chat_dispatch);
MUI_DISPATCH_DECL(gchat_dispatch);
MUI_DISPATCH_DECL(read_dispatch);
MUI_DISPATCH_DECL(agents_dispatch);
MUI_DISPATCH_DECL(register_dispatch);
MUI_DISPATCH_DECL(chatarea_dispatch);
MUI_DISPATCH_DECL(prefs_dispatch);
MUI_DISPATCH_DECL(presence_dispatch);
MUI_DISPATCH_DECL(xfer_dispatch);
MUI_DISPATCH_DECL(xfer_req_dispatch);
MUI_DISPATCH_DECL(xmlform_dispatch);
MUI_DISPATCH_DECL(search_dispatch);
MUI_DISPATCH_DECL(search_result_dispatch);



struct rosterdata {
	Object *list, *popupmenu;
	juser popupuser;
	Object *chatmenu, *writemenu, *infomenu, *addmenu, *accsubmenu, *submenu, *unsubmenu, *remmenu;
	Object *unavail_pix, *avail_pix, *chat_pix, *away_pix, *xaway_pix, *dnd_pix, *msg_pix;
};

#define ROSTER_CLOSEME 0x0501
#define ROSTER_DOUBLECLICK 0x0502
#define ROSTER_MENU 0x0503

enum
{
	ROSTER_READ,
	ROSTER_CHAT,
	ROSTER_INFO,
	ROSTER_ACCEPT,
	ROSTER_SUBS,
	ROSTER_REMOVE,
	ROSTER_SEND
};

struct condata {
	Object *list,*texted;
	Object *xmltog;
};


#define CON_MSG 0x1001
#define CON_FLUSH 0x1002
#define CON_SAVE 0x1003
#define CON_SEND 0x1004
#define CON_TOGGLEXML 0x1005

struct logindata {
	Object *me, *ti, *idstr, *pstr, *savetog, *help;
};


#define LOGIN_OPEN 0x1501
#define LOGIN_CONNECT 0x1502



struct writedata
{
	Object *tostr, *substr, *texted;
};

#define WRITE_TO 0x2001
#define WRITE_SEND 0x2002
#define WRITE_THREAD 0x2003
#define WRITE_QUOTE 0x2004


struct contactdata
{
	Object *idstr, *namestr, *greetstr;
};

#define CONTACT_ADD 0x3001
#define CONTACT_JID 0x3002
#define CONTACT_NAME 0x3003



struct userinfodata
{
	juser u;
	Object *namestr;
	Object *clientstr, *verstr, *osstr;
};

#define USERINFO_OF 0x3001
#define USERINFO_UPDATE 0x3002
#define USERINFO_CLOSE 0x3003
#define USERINFO_ASKVER 0x3004


struct chatdata
{
	juser user;
	Object *list, *str;
};

#define CHAT_WITH 0x3501
#define CHAT_SEND 0x3502
#define CHAT_MSG 0x3503
#define CHAT_FLUSH 0x3504


struct gc_user
{
	listitem node;
	struct gc_win *gcw;
	char *nick;
};

struct gc_win
{
	listitem node;
	Object *win;
	iksid *id;
	list *users;
	int state;
	int people;
	struct gchatdata *data;
};

struct gchatdata
{
	Object *chantxt, *topicstr, *msglist, *userlist, *numtxt;
	Object *rect, *nicktxt, *msgstr;
	struct gc_win *gcw;
	char *nick;
};

#define GCHAT_SEND 0x3601
#define GCHAT_PACKET 0x3602
#define GCHAT_CLOSE 0x3603
#define GCHAT_TOPIC 0x3604



struct readdata
{
	juser user;
	Object *prevbut, *stat, *nextbut;
	Object *thread, *text, *fromtxt;
	Object *errorlab, *errortxt;
};

#define READ_PREV 0x4001
#define READ_REPLY 0x4002
#define READ_NEXT 0x4003
#define READ_FROM 0x4004
#define READ_WRITE 0x4005
#define READ_CLOSE 0x4006
#define READ_UPDATE 0x4007

struct agentsdata
{
	Object *list, *url, *desc;
	Object *regbut, *searchbut, *urlbut;
};

#define AGENTS_PARSE 0x4501
#define AGENTS_UPDATEINFO 0x4502
#define AGENTS_REG 0x4503
#define AGENTS_SEARCH 0x4504
#define AGENTS_URL 0x4505



struct registerdata
{
	Object *xform;
	ikspak *pak;
};

#define REGISTER_PACKET 0x5001
#define REGISTER_SEND 0x5002
#define REGISTER_ABANDON 0x5003



struct chatareadata
{
	Object *list;
	void *pool;
};

#define CHATAREA_ADD 0x5501
#define CHATAREA_FLUSH 0x5502



struct prefsdata
{
	Object *pagelist, *pagearea;
	Object *icontog, *autocontog, *recontog;
	Object *eventlist, *showtog, *wintog, *scrtog, *cmdstr, *sndstr;
	long lastitem;
	Object *authtog;
	Object *xintog, *xouttog, *debugtog, *logfilestr;
};

#define PREFS_CANCEL 0x6001
#define PREFS_SAVE 0x6002
#define PREFS_USE 0x6003
#define PREFS_TESTSND 0x6004
#define PREFS_OPEN 0x6005
#define PREFS_ENTRY 0x6006
#define PREFS_LASTSAVED 0x6007
#define PREFS_PAGE 0x6008


#define PRESENCE_BUTTON 0x6501


enum xfertypes
{
	XFER_SEND,
	XFER_RECEIVE
};

enum xferstates
{
	XFER_OFFERING,
	XFER_OFFERED,
	XFER_CONNECTED,
	XFER_CONNECTING,
	XFER_REQUESTING,
	XFER_SENDING,
	XFER_RECEIVING,
	XFER_FINISHED,
	XFER_REJECTED,
	XFER_TIMEOUT,
	XFER_ERROR
};

struct xferdata
{
	listitem node;
	enum xfertypes type;
	int state;
	char *file;
	char *name;
	u_long size, cursize;
	ikspak *pak;
};

struct xferreqdata
{
	char *jid;
	Object *filestr, *descstr;
};

list *xfers;

#define TRANSFER_TO 0x7001
#define TRANSFER_SEND 0x7002
#define TRANSFER_OP 0x7003



struct xmlformdata
{
	char *key;
	ikspak *pak;
	list *items;
};

#define XMLFORM_PACKET 0x7501
#define XMLFORM_PRINT 0x7502



struct searchdata
{
	Object *xform;
	ikspak *pak;
};

struct searchresultdata
{
	Object *list;
	ikspak *pak;
};

#define SEARCH_PACKET 0x8001
#define SEARCH_GO 0x8002
#define SEARCH_ADD 0x8003



/*****  Prototypes  *****/

#define list_first(x) (void *)(*( x ))->first
#define list_next(x) (void *)( x )->node.next
#define list_prev(x) (void *)( x )->node.prev
listitem *list_append(list **lis, void *data);
listitem *list_prepend(list **lis, void *data);
void list_remove(list **lis, void *data);
void list_remove_all(list **lis);


char *my_printf(char *fmt, ...);
char *my_vprintf(char *fmt, va_list ap);

void open_url(char *url);



void gui_run(void);
void gui_state(char *msg);


char *about_version(void);
char *about_version_mui(void);


#ifdef NOMORPHOS
extern struct EmulLibEntry console_logger;
#else
void SAVEDS console_logger(void *udata, char *xml, int dir);
#endif
void con_debug(char *msg, ...);

void net_connect(void);
void net_disconnect(char *msg);
void net_listen(void);

void write_to(char *to, char *thread, char *body);
void contact_add(void);
void contact_ask(char *jid, char *name);
void read_from(juser u);

void roster_fetch(void);
void roster_reset(void);
void roster_update(ikspak *pak);
void roster_update_presence(ikspak *pak);
juser roster_find(iksid *id);
juser roster_locate(iksid *id);
void roster_remove(juser u);
void roster_refresh(juser u);
juser roster_next(int i);

void userinfo_of(juser u);
void userinfo_update(ikspak *pak);

void chat_with(juser u);

void gchat_on(char *chan);
int gchat_packet(ikspak *pak);

void prf_setup(int argc, char *argv[]);
void prf_load(char *fname);
void prf_save(char *fname);
void prf_load_account(void);
void prf_save_account(void);
void prf_event(int evt, ...);


void agents_fetch(void);

void convert_select(char *fname);
char *convert_utf8(char *src);
char *convert_locale(char *src);

void presence_ask(ikspak *pak);

void xfer_packet(ikspak *pak);
void xfer_share(juser u);
void xfer_refresh(struct xferdata *xf);


int http_up(void);
void http_down(void);
void http_listen(void);


Object *xmlform_create(ikspak *pak);
iks *xmlform_print(Object *obj);


void search_display(ikspak *pak);


#endif	/* INCL_COMMON_H */
