#define MOD_PATH "modules/"

/* Special "access" routines */

#include <clib/exec_protos.h>
#include <clib/wb_protos.h>
#include <clib/alib_protos.h>
#include <clib/commodities_protos.h>
#include <clib/intuition_protos.h>
#include <clib/dos_protos.h>
#include <libraries/commodities.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <intuition/intuition.h>
#include <clib/intuition_protos.h>
#include <exec/exec.h>
#include <intuition/screens.h>
#include <rexx/storage.h>
#include <clib/rexxsyslib_protos.h>
#include <libraries/arq.h>
#include <clib/icon_protos.h>
#include <workbench/startup.h>
#include <workbench/workbench.h>
#include <proto/locale.h>
#include <proto/screennotify.h>
#include <libraries/screennotify.h>

#include "prefs.h"

/* #define DEBUG_CODE */

struct Message *a_msg=NULL;
struct MsgPort *CxMsgPort=NULL, *CxHotKey1=NULL, *CxHotKey2=NULL, *RexxPort=NULL,*SNPort;
CxObj *CommObj, *hk1, *hk2;
CxMsg *CxMessage;

struct Library *IconBase=NULL;
struct Library *ScreenNotifyBase;

extern struct Window *win_p;
extern BOOL talk(char *text);
extern char line2[200];
extern char line1[200];
extern struct Menu menu1;
extern BOOL loadpic(char *fname, struct Screen *screen);
extern void refreshwindow(void);
extern char *trans(char *text);
extern BOOL ispicture;
extern void changemenu(void);
extern BOOL exit_flag;
extern void msg(char *msg);
extern struct NewWindow win1;
extern void closeall(void);
extern void setupmainwindow(void);

extern struct Screen *pubscreen;
extern struct Library *CxBase;
extern struct IntuitionBase *IntuitionBase;
extern struct GfxBase *GfxBase;
extern struct Library *UtilityBase;
extern struct Library *GadToolsBase;
extern struct Library *DiskfontBase;
extern struct Library *AslBase;
extern struct Library *IFFParseBase;
extern struct Library *DOSBase;
extern struct Library *RexxSysBase;

BOOL cxinit(void);
BOOL arexxinit(void);
BOOL sninit(void);
void cxclose(void);
void arexxclose(void);
void snclose(void);
void process_arexx(void);
void process_args(int count, char *args[]);
void process_wbargs(struct WBStartup *wbs);

static struct NewBroker newbrok = {
	NB_VERSION,
	"EngClock 1",
	"EngClock v8.5 © 1997 by Ben Matthew",
	"A clock with words!",
	NBU_UNIQUE|NBU_NOTIFY,
	COF_SHOW_HIDE,
	0,
	0,
	0
};


extern BOOL locale;
extern struct Language *chosen_lang;
extern struct Language *available_lang;
extern struct Catalog *catalog;
extern struct Prefs prefs;
extern int winx, winy, winh, winw;
extern BOOL reset_all;
extern BOOL no_reset_font;
extern struct {
	int s_width;       /* Width of current screen */
	int s_height;      /* Height of current screen */
	int s_bar;         /* Bar height of windows.  Other font */
	int s_cols;        /* Number of colours available */
	int s_mode;        /* Mode according to s_cols (Depth) */
}screentype;
extern struct Library *LangModBase;
extern void unloadpic(struct Picture pic);
extern struct Picture piccy;
extern BOOL ispicture;
extern struct TextFont *win_font;

APTR snhandle1, snhandle2;

BOOL sninit(void) {
	if(!(ScreenNotifyBase=OpenLibrary(SCREENNOTIFY_NAME, SCREENNOTIFY_VERSION))) {
		return(0);
	}
	
	if(!(SNPort=CreateMsgPort())) {
		CloseLibrary(ScreenNotifyBase);	
		return(0);
	}
	
	if(!(snhandle1=AddWorkbenchClient(SNPort,0))) {
		CloseLibrary(ScreenNotifyBase);	
		DeleteMsgPort(SNPort);
		return(0);
	}
	
	return(1);
}

void snclose(void) {
	struct Message *msg;
	
	while(msg=GetMsg(SNPort))
		ReplyMsg(msg);

	while(!RemWorkbenchClient(snhandle1)) Delay(25);
	snhandle1=NULL;
	
	DeleteMsgPort(SNPort);
	SNPort=NULL;
	
	CloseLibrary(ScreenNotifyBase);
	
}

BOOL cxinit(void) {
	char comtext[50], tmp[10];
	int count=1;
	
	#define MAXBROKERS 10

	if(!CxBase) 
		return(0);

	CxMsgPort=CreateMsgPort();
	CxHotKey1=CreateMsgPort();
	CxHotKey2=CreateMsgPort();

	if(!(CxMsgPort && CxHotKey1 && CxHotKey2)) 
		return(0);
	
	newbrok.nb_Port=CxMsgPort;
	while(!(CommObj=CxBroker(&newbrok,NULL))) {
		count++;
		if(count==MAXBROKERS) break;
		strcpy(comtext,"EngClock ");
		sprintf(tmp,"%d",count);
		strcat(comtext,tmp);
		newbrok.nb_Name=comtext;
	}
	if(!CommObj) {
		
		DeleteMsgPort(CxMsgPort);
		CxMsgPort=NULL;
		return(0);
	} else
		ActivateCxObj(CommObj,1L);

	
	hk1=HotKey(prefs.tkey,CxHotKey1,1234);
	hk2=HotKey(prefs.hkey, CxHotKey2,9999);

	if(!(hk1 && hk2)) {
		if(hk1) DeleteCxObj(hk1);
		if(hk2) DeleteCxObj(hk2);
		DeleteMsgPort(CxHotKey1);
	} else {
		AttachCxObj(CommObj,hk1);
		AttachCxObj(CommObj,hk2);
		ActivateCxObj(CommObj,1L);
	}	
	
	return(1);
}

void cxclose(void) {

	if(CommObj) 
		DeleteCxObjAll(CommObj);

	
	if(CxMsgPort) {
		while(CxMessage=(CxMsg *)GetMsg(CxMsgPort)) 
			ReplyMsg((struct Message *)CxMessage);
		
		DeleteMsgPort(CxMsgPort);
		CxMsgPort=NULL;
	}

	if(CxHotKey1) {
		while(CxMessage=(CxMsg *)GetMsg(CxHotKey1)) 
			ReplyMsg((struct Message *)CxMessage);
		
		DeleteMsgPort(CxHotKey1);
		CxHotKey1=NULL;
	}

	if(CxHotKey2) {
		while(CxMessage=(CxMsg *)GetMsg(CxHotKey2)) 
			ReplyMsg((struct Message *)CxMessage);
		
		DeleteMsgPort(CxHotKey2);
		CxHotKey2=NULL;
	}

	return;
}

/* Now a simple routine that is used in main() to check what the user 
wants to do about a menu selection */

BOOL wb_ask(char *body, char *opt1, char *opt2) {
	struct ExtEasyStruct deadeasy;
	char string[500];
	char params[100];

	strcpy(string,"English Clock v6.9\n\n");
	strcat(string,body);
	strcpy(params,opt2);
	strcat(params,"|");
	strcat(params,opt1);

	deadeasy.Magic=ARQ_MAGIC;
	deadeasy.AnimID=ARQ_ID_QUESTION;
	deadeasy.Easy.es_Title=" ";
	deadeasy.Easy.es_TextFormat=string;
	deadeasy.Easy.es_GadgetFormat=params;

	return((BOOL)EasyRequest(NULL,&deadeasy.Easy,NULL,NULL));

}

BOOL arexxinit(void) {
	Forbid();
	if(FindPort("ENG_REXX")) {
		Permit();
		return(0);
	}
	if(!(RexxPort=(struct MsgPort *)CreatePort("ENG_REXX",0))) {
		Permit();
		return(0);
	}
	Permit();
	
	// Best to set up RexxBase as well

	if(!(RexxSysBase=OpenLibrary("rexxsyslib.library",0))) {
		DeletePort(RexxPort);
		return(0);
	}
			
	// And thats it!

	return(1);

}

void arexxclose(void) {
	struct Message *a_mess=NULL;

	while(a_mess=GetMsg(RexxPort))
		ReplyMsg(a_mess);
	
	Forbid();
	DeletePort(RexxPort);
	Permit();
	RexxPort=NULL;

	if(RexxSysBase) CloseLibrary(RexxSysBase);
	RexxSysBase=NULL;
}

struct QuickMsg {
	struct Message base;
	char id[20];
	char msg[500];
};

void process_arexx(void) {
	struct RexxMsg *rexxmsg=NULL;
	struct QuickMsg *qmsg=0;
	char string[50];
	char newspeak[200];
	char *ptr=0, *ptr2=0;
	char string2[50];
	BPTR file;
	int x, y, width, height, count=7, gotted=0, len;

	while(qmsg=(struct QuickMsg *)GetMsg(RexxPort)) {

		// We have a message, but what is it!

		if(strcmp(qmsg->id,"THIS IS A QUICKMSG!")) {
			rexxmsg=(struct RexxMsg *)qmsg;
			ptr=CreateArgstring(rexxmsg->rm_Args[0],strlen(rexxmsg->rm_Args[0]));
			sprintf(string,"%s",ptr);
		} else
			sprintf(string,"%s",qmsg->msg);
			
		if(!strcmp(string,"SPEAK")) {
			strcpy(newspeak,line1);
			if(!strcmp(chosen_lang->name,"english")) newspeak[strlen(newspeak)-4]=NULL;  /* Get rid of pm/am */
			strcat(newspeak,".  ");
			strcat(newspeak,line2);
			newspeak[strlen(newspeak)-6]=NULL; /* Get rid of year */
			talk(trans(newspeak));
		}	
		if(!strcmp(string,"ACTIVATE")) {
			WindowToFront(win_p);
		}
		if(!strcmp(string,"QUIT")) {
			exit_flag=TRUE;
		}
		if(!strcmp(string,"RESET")) {
			reset_all=TRUE;
		}
		
		if(!strcmp(string,"LEFT")) {
			prefs.just=0;
			refreshwindow();
		}
		if(!strcmp(string,"RIGHT")) {
			prefs.just=2;
			refreshwindow();
		}
		if(!strcmp(string,"CENTRE")) {
			prefs.just=1;
			refreshwindow();
		}
		if(!strcmp(string,"AUTO ON")) {
			prefs.autoadjust=1;
			refreshwindow();			
		}
		if(!strcmp(string,"AUTO OFF")) {
			prefs.autoadjust=0;
			refreshwindow();			
		}
		if(!strcmp(string,"DATE ON")) {
			prefs.date=1;
			refreshwindow();			
		}
		if(!strcmp(string,"DATE OFF")) {
			prefs.date=0;
			refreshwindow();			
		}
		strcpy(string2,string);
		string2[7]=0;
		if(!strcmp(string2,"TIMECOL")) {
			ptr2=&string2[8];
			prefs.time_col[screentype.s_mode]=atoi(ptr2);
			refreshwindow();
		}
		strcpy(string2,string);
		string2[7]=0;
		if(!strcmp(string2,"DATECOL")) {
			ptr2=&string2[8];
			prefs.date_col[screentype.s_mode]=atoi(ptr2);
			refreshwindow();
		}
		strcpy(string2,string);
		string2[4]=0;
		if(!strcmp(string2,"LANG")) {
			struct Library *tbase=0;
			ptr2=&string2[5];
			
			if(1) {
				char name[100];
				char tmp[80];
		
				strcpy(name,MOD_PATH);
				sprintf(tmp,"%s.langmod",ptr2);
				strcat(name,tmp);
			
				tbase=OpenLibrary(name,0);
		
			}
			
			if(tbase) {
				CloseLibrary(LangModBase);
				LangModBase=tbase;
				strcpy(chosen_lang->name,ptr2);
			}
			refreshwindow();
		}

		strcpy(string2,string);
		string2[8]=NULL;
		if(!strcmp(string2,"SENDPORT")) {
			ptr2=&string2[9];
			if(file=Open(ptr2,MODE_OLDFILE)) {
				Write(file,line1,strlen(line1));
				Close(file);
			}
		}
		if(!strcmp(string2,"SENDFILE")) {
			ptr2=&string2[9];
			if(file=Open(ptr2,MODE_READWRITE)) {
				Write(file,line1,strlen(line1));
				Close(file);
			}
		}
		strcpy(string2,string);
		string2[6]=NULL;
		if(!strcmp(string2,"SCREEN")) {
			struct Screen *t;
			
			ptr2=&string2[7];
			if(t=LockPubScreen(ptr2)) {
				UnlockPubScreen(NULL,pubscreen);
				pubscreen=t;
				win1.Screen=pubscreen;
				
				sprintf(prefs.pub,"%s",ptr2);
				
				reset_all=TRUE;
				no_reset_font=TRUE;
			}
			
			
		}
		strcpy(string2,string);
		string2[4]=0;
		if(!strcmp(string2,"FONT")) {
			ptr2=&string2[5];
			sscanf(ptr2,"%s %d %d",&prefs.fontname,&prefs.fontsize,&prefs.fontstyle);
			reset_all=TRUE;
			no_reset_font=TRUE;
		}
		strcpy(string2,string);
		string2[6]=0;
		if(!strcmp(string2,"ACCENT")) {
			ptr2=&string2[7];
			sprintf(prefs.accent,"%s",ptr2);
		}
		strcpy(string2,string);
		string2[5]=NULL;
		if(!strcmp(string2,"PICCY")) {
			ptr2=&string2[6];
			sprintf(prefs.backdrop,ptr2);
			reset_all=TRUE;
			no_reset_font=TRUE;
		}
		strcpy(string2,string);
		string2[6]=NULL;
		count=7;
		if(!strcmp(string2,"NEWWIN")) {
			strcpy(string2,string); /* Re-init string2 */
			ptr2=&string2[7];
			len=strlen(string2);
			while(count <= len) {
				if(string[count]==NULL)  /* End of line yet? */
					height=atoi(ptr2);
				

				if(string2[count]==',') {
					string2[count]=NULL;

					switch(gotted) {
						case 0:
							x=atoi(ptr2);
						break;
						case 1:
							y=atoi(ptr2);
						break;
						case 2:
							width=atoi(ptr2);
						break;
					}
					gotted++;
					ptr2=&string2[count]+1;
				}	
				
				count++;
			}
			if(gotted==3) {
				// If not there has been a parse error
				//prefs.x=x;
				//prefs.y=y;
				//prefs.width=width;
				//prefs.height=height;
				ClearMenuStrip(win_p);
				CloseWindow(win_p);
				setupmainwindow();
				if(!(win_p=OpenWindow(&win1))) {
					msg(GetCatalogStr(catalog,24,"Error re-opening window!"));
					// Best to reply before bye
					ReplyMsg((struct Message *)rexxmsg);
					closeall();
					exit(NULL);
				}
				SetMenuStrip(win_p,&menu1);
				refreshwindow();
			}
		}


		ReplyMsg((struct Message *)qmsg);
		if(ptr) DeleteArgstring(ptr);
	}
	
}	
	

void process_args(int count, char *args[]) {
	// Quicky to process command line args

	int i=0, j=0;
	char byte;
	char byte_s[2];
	char string[200], string2[200];

	// is it from wb?

	if(count==0)
		process_wbargs((struct WBStartup *)args);

	// is there any args?
	
	if(count<2) 
		return;

	// Right ok we have some

	for (i=1; i<count; i++) {
		strcpy(string2,"");
		//printf("Testing arg: %d\n",i);
		strcpy(string,args[i]);
		//printf("which is: %s\n",string);
		for(j=0; j<strlen(args[i]); j++) {
			byte=string[j];
			if(byte != '=') {
				sprintf(byte_s,"%c",byte);	
				strcat(string2,byte_s);
			}
			else {
				//printf("found sign!\n");
				//printf("s2 is now: %s\n",string2);
				if(!(strcmp(string2,"X"))) {
					//prefs.x=atoi(&string[j+1]);
					winx=atoi(&string[j+1]);
					//printf("X is %d\n",atoi(&string[j+1]));
				}
				if(!(strcmp(string2,"Y"))) {
					//prefs.y=atoi(&string[j+1]);
					winy=atoi(&string[j+1]);
					//printf("Y is %d\n",atoi(&string[j+1]));
				}
				if(!(strcmp(string2,"WIDTH"))) {
					//prefs.width=atoi(&string[j+1]);
					winh==atoi(&string[j+1]);
					//printf("WIDTH is %d\n",atoi(&string[j+1]));
				}
				if(!(strcmp(string2,"HEIGHT"))) {
					//prefs.height=atoi(&string[j+1]);
					winw=atoi(&string[j+1]);
					//printf("HEIGHT is %d\n",atoi(&string[j+1]));
				}
				 if(!(strcmp(string2,"PUBSCREEN"))) {
					strcpy(prefs.pub,&string[j+1]);
					//printf("PUBSCREEN is %s\n",&string[j+1]);
				}
				if(!(strcmp(string2,"JUSTIFICATION"))) {
					prefs.just=atoi(&string[j+1]);
					//printf("PUBSCREEN is %s\n",&string[j+1]);
				}
				if(!(strcmp(string2,"DATE"))) {
					if(!(strcmp(&string[j+1],"YES")))	
						prefs.date=1;
					else 
						prefs.date=0;
					//printf("PUBSCREEN is %s\n",&string[j+1]);
				}
				if(!(strcmp(string2,"WTF"))) {
					if(!(strcmp(&string[j+1],"YES")))	
						prefs.wtf=1;
					else 
						prefs.wtf=0;
					//printf("PUBSCREEN is %s\n",&string[j+1]);
				}
				if(!(strcmp(string2,"ADJUST"))) {
					if(!(strcmp(&string[j+1],"YES")))	
						prefs.autoadjust=1;
					else 
						prefs.autoadjust=0;
					//printf("PUBSCREEN is %s\n",&string[j+1]);
				}
				if(!(strcmp(string2,"BACKDROP"))) {
					strcpy(prefs.backdrop,&string[j+1]);
					//printf("PUBSCREEN is %s\n",&string[j+1]);
				}
				if(!(strcmp(string2,"ACCENT"))) {
					strcpy(prefs.accent,&string[j+1]);
					//printf("PUBSCREEN is %s\n",&string[j+1]);
				}
				if(!(strcmp(string2,"TALKKEY"))) {
					strcpy(prefs.tkey,&string[j+1]);
					//printf("PUBSCREEN is %s\n",&string[j+1]);
				}
				if(!(strcmp(string2,"HOTKEY"))) {
					strcpy(prefs.hkey,&string[j+1]);
					//printf("PUBSCREEN is %s\n",&string[j+1]);
				}
			}
		}
	}
}

void process_wbargs(struct WBStartup *wbs) {
	struct DiskObject *dobj;
	char *result;
	
	if(!(IconBase=OpenLibrary("icon.library",0))) {
		msg(GetCatalogStr(catalog,40,"Unable to open icon library!"));
		return;
	}

	dobj=GetDiskObject(wbs->sm_ArgList->wa_Name);	
	if(!dobj) {
		msg(GetCatalogStr(catalog,39,"Unable to get disk object!"));
		CloseLibrary(IconBase);
		return;
	}
	
	// Code to find tool tpes here
	
	if(result=FindToolType(dobj->do_ToolTypes,"X")) 
		//prefs.x=atoi(result);
		winx=atoi(result);
	if(result=FindToolType(dobj->do_ToolTypes,"Y")) 
		//prefs.y=atoi(result);
		winy=atoi(result);
	if(result=FindToolType(dobj->do_ToolTypes,"WIDTH")) 
		//prefs.width=atoi(result);
		winw==atoi(result);
	if(result=FindToolType(dobj->do_ToolTypes,"HEIGHT")) 
		//prefs.height=atoi(result);
		winh==atoi(result);
	if(result=FindToolType(dobj->do_ToolTypes,"JUSTIFICATION")) 
		prefs.just=atoi(result);

	if(result=FindToolType(dobj->do_ToolTypes,"DATE")) {
		if(!(strcmp(result,"YES"))) 
			prefs.date=1;
		else
			prefs.date=0;
	}
	if(result=FindToolType(dobj->do_ToolTypes,"WTF")) {
		if(!(strcmp(result,"YES"))) 
			prefs.wtf=1;
		else
			prefs.wtf=0;
	}
	if(result=FindToolType(dobj->do_ToolTypes,"ADJUST")) {
		if(!(strcmp(result,"YES"))) 
			prefs.autoadjust=1;
		else
			prefs.autoadjust=0;
	}
	
	if(result=FindToolType(dobj->do_ToolTypes,"PUBSCREEN")) 
		strcpy(prefs.pub,result);
	if(result=FindToolType(dobj->do_ToolTypes,"ACCENT")) 
		strcpy(prefs.accent,result);
	if(result=FindToolType(dobj->do_ToolTypes,"TALKKEY")) 
		strcpy(prefs.tkey,result);
	if(result=FindToolType(dobj->do_ToolTypes,"HOTKEY")) 
		strcpy(prefs.hkey,result);
	if(result=FindToolType(dobj->do_ToolTypes,"BACKDROP")) 
		strcpy(prefs.backdrop,result);
	
	FreeDiskObject(dobj);
	CloseLibrary(IconBase);
}