/* Data and prototypes that are shared by both client and server */

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

#include <dos/dos.h>
#include <dos/dostags.h>

#include <exec/types.h>
#include <exec/io.h>
#include <exec/lists.h>
#include <exec/memory.h>

#include <clib/commodities_protos.h>
#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <clib/dos_protos.h>
#include <clib/socket_protos.h>

#include <errno.h>
#include <inetd.h>
#include <time.h>
#include <sys/types.h>

#include <proto/socket.h>
#include <sys/errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/syslog.h>
#include <netdb.h>


#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <intuition/gadgetclass.h>
#include <intuition/screens.h>
#include <libraries/gadtools.h>
#include <clib/icon_protos.h>
#include <clib/wb_protos.h>
#include <clib/intuition_protos.h>
#include <clib/diskfont_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/graphics_protos.h>

#include <pragmas/socket_pragmas.h>
#include <devices/timer.h>

#include <libraries/diskfont.h>
#include <libraries/commodities.h>

#define UNLESS(x) if(!(x))

#define AMITRACK_TIMEOUT_MINUTES 5

/* Possible Request bits for the first data byte of the UDP packets */
#define REQ_COMMENT 0x01	/* "My comment is now this string:" */
#define REQ_BYE	    0x02	/* "I'm quitting, remove me immediately" */

#define EVT_HOTKEY  1

/* Used internally by the event loops */
#define CODE_UDP_SOCKET    0x0001 /* "You've got a UDP packet ready to read" */
#define CODE_TCP_SOCKET    0x0002 /* "You've got a TCP connection ready" */
#define CODE_TIMER_EXPIRED 0x0004 /* "The timer expired." */
#define CODE_REFRESH       0x0008 /* "Please redraw the client list." */
#define CODE_WINDOW_EVENT  0x0010 /* "Check for IDCMP stuff." */
#define CODE_PING          0x0020 /* "Send a ping, please." */
#define CODE_RECONNECT	   0x0040 /* "Possibly reconnect to another server/port" */
#define CODE_HIDE          0x0080 /* "Close your window." */
#define CODE_SHOW          0x0100 /* "Show your window." */
#define CODE_ENABLE        0x0200 /* "Resume pinging & updating" */
#define CODE_DISABLE       0x0400 /* "Stop automatic pinging & updating" */
#define CODE_MSGPORT	   0x0800 /* "A message is at your message port." */
#define CODE_QUIT          0x1000 /* "Die! Die! Die!" */

/* Since TCP and UDP have separate port domains, I can use the same port numbers
   for the UDP and TCP ports */
#define SERVER_UDP_PORT 18945	/* UDP port for the server process */
#define SERVER_TCP_PORT 18945	/* TCP port for the server process */

struct ClientList {
	struct List list;
	int nListLength;
};

struct Client {
	struct Node node;
	time_t tDateStamp;
	char * hostname;
	char * comment;
	ULONG ulIPAddress;
};

struct TimerStuff {
	struct MsgPort     * TimerMP;
	struct timerequest * TimerIO;
	BOOL BDevOpen;
};

struct SocketStuff {
	LONG fd;		/* socket # */
	LONG lSocketType;	/* either SOCK_STREAM or SOCK_DGRAM, please */
	struct sockaddr_in saAddr;
};

struct CxStuff {
    CxObj * broker;
    struct MsgPort * port;
    struct NewBroker nb;
    char * name;
};

struct WindowStuff {
	struct Screen * screen;		/* Pointer to screen we're on */
	struct Window * win;		/* Pointer to Intuition window structure */
	struct TextAttr font;		/* Gadget rendering font */
	struct TextFont * fontdata;	/* The font's bits */
	struct TextAttr fixedfont;	/* ListView rendering font */
	struct TextFont * fixedfontdata; /* This font's bits */
	void 	      * vi;              /* visual info for gadgets */
	struct Gadget * glist;		     /* list of all our gadgets */
	struct Gadget * ListGadget;	     /* ListView of all logins */
	struct Gadget * PingButton;	     /* Manual ping */
	struct Gadget * UpdateButton;	 /* Manual update */
	struct Gadget * ServerString;	 /* Server display/chooser string */
	struct Gadget * PortString;	     /* Port display/chooser string */
	struct Gadget * ActionCycle;     /* Cycle to choose wdich action will be performed on double-click in the ListView */
	struct Gadget * CommentString;	 /* Comment display/chooser string */
	struct Gadget * UpdateIntString; /* Choose list refresh interval */
	struct Gadget * PingIntString;   /* Choose ping interval */
};






/* Shared functions */
struct ClientList * SetupClientList(struct ClientList * clientList);
struct TimerStuff * SetupTimer(struct TimerStuff * ts);
struct SocketStuff * SetupSocket(struct SocketStuff * ss, int nPort, LONG lSocketType);

void TrackWait(struct SocketStuff * TCPStuff, struct SocketStuff * UDPStuff, struct TimerStuff * Timer, 
               struct WindowStuff * Window, struct MsgPort * msgport, 
               struct CxStuff * cx);

void SetTrackFlag(ULONG flag);
BOOL CheckTrackFlag(ULONG flag);
BOOL TrackFlagsSet(void);

struct Client * NewClient(ULONG ulIPAddress, char * szHostName, char * szOptComment);
void FreeClient(struct Client * client);
BOOL isEqual(struct Client *, struct Client *);

void ReplaceAllocedString(char ** szOldString, char * szNewString);
void SetTimer(struct TimerStuff * ts, int nSecs, int nMicros);
void TrackExit(char * szMessage, int nCode);

struct Client * GetClient(struct ClientList * ClientList, ULONG ulIPAddr, char * szHostName, char * szOptComment);
BOOL RemoveClient(struct ClientList * ClientList, char * szHostName);
BOOL FillInfos(struct SocketStuff * sSocket, char **pSetName, ULONG * ulIPAddress, char **pSetComment);
void PrintClientList(struct ClientList *);
void ClearTrackScreen(void);

struct ClientList * GetTrackList(char * szHostName, int nPortNum);

int MakeReq(char *sTitle, char *sText, char *sGadgets);

char * PastSpaces(char * pcString);
char * RemoveUnprintableChars(char * pcString);
char * RemoveTrailingSpaces(char * pcString);
char * ToLower(char * pcString);