#include "WriteMainFile.h"
#include "Tools.h"
#include "MB_protos.h"
#include "MB_pragmas.h"
#include "mb.h"

#include <proto/exec.h>
#include <proto/dos.h>
#include <stdlib.h>
#include <string.h>

#define HEADER_END_MSG 				"/* GenCodeC header end */"
#define	HEADER_END					HEADER_END_MSG "\n"
#define	LIBRARY_DECLARATION_MSG		"/* Declarations for libraries (inserted by GenCodeC) */"
#define	LIBRARY_DECLARATION			LIBRARY_DECLARATION_MSG "\n"
#define	LIBRARY_MUI_MSG				"struct Library * MUIMasterBase"
#define	LIBRARY_MUI					LIBRARY_MUI_MSG ";\n"
#define	LIBRARY_LOCALE_MSG			"struct Library * LocaleBase"
#define	LIBRARY_LOCALE				LIBRARY_LOCALE_MSG ";\n"
#define OPEN_LOCALE_LIBRARY_MSG		"if (!(LocaleBase = OpenLibrary(\"locale.library\",38)))"
#define OPEN_LOCALE_LIBRARY			"\t" OPEN_LOCALE_LIBRARY_MSG "\n"
#define CLOSE_LOCALE_LIBRARY_MSG	"CloseLibrary(LocaleBase)"
#define CLOSE_LOCALE_LIBRARY		CLOSE_LOCALE_LIBRARY_MSG ";\n"
#define CLOSE_LIBRARY_MSG			"CloseLibrary"
#define CLOSE_LIBRARY				"\t" CLOSE_LIBRARY_MSG
#define	INIT_BEGIN_MSG				"/* Init() function */"
#define	INIT_BEGIN					"\n" INIT_BEGIN_MSG "\n"
#define	INIT_END_MSG				"/* GenCodeC init() end */"
#define	INIT_END					"}\n" INIT_END_MSG "\n"
#define	END_BEGIN_MSG				"/* End() function */"
#define	END_BEGIN					"\n" END_BEGIN_MSG "\n"
#define	END_END_MSG					"/* GenCodeC end() end */"
#define	END_END						"}\n" END_END_MSG "\n"
#define	OPEN_CATALOG_MSG			"OpenAppCatalog(NULL,NULL)"
#define	OPEN_CATALOG				OPEN_CATALOG_MSG ";\n"
#define	CLOSE_CATALOG_MSG			"CloseAppCatalog()"
#define	CLOSE_CATALOG				"\t" CLOSE_CATALOG_MSG ";\n"
#define	CASE_BEGIN_MSG				"/* Insert your code between the \"case\" statement and comment \"end of case ...\" */"
#define	CASE_BEGIN					CASE_BEGIN_MSG "\n"
#define	CASE_END_MSG				"/* End computing of IDCMP */"
#define	CASE_END					CASE_END_MSG "\n"

/****************************************************************************************************************/
/*****																										*****/
/**								 				WriteIDCMP													   **/
/*****																										*****/
/****************************************************************************************************************/

static char *WriteIDCMP(FILE *file,char *buf,ULONG varnb,BOOL OldMainExists)
{
	int		i;
	char 	*name;
	char	*tmp;
	ULONG	type;
	char 	*str;
	char	*str1;
	char	ctmp;

	/* Write IDCMPs */
	for(i=0;i<varnb;i++)
	{
		MB_GetVarInfo(i,
					  MUIB_VarType,&type,
					  MUIB_VarName,&name,
					  TAG_END);
		tmp = AllocMemory(strlen(name)+19,TRUE);
		strcpy(tmp,"case ");
		strcat(tmp,name);
		strcat(tmp,":");
		if (type == TYPEVAR_IDENT)
		{
			if (OldMainExists && (str = strstr(buf,tmp)))
			{
				/* Write old IDCMP */
				strcpy(tmp,"/* end of case ");
				strcat(tmp,name);
				strcat(tmp," */");
				if (!(str1=strstr(str,tmp)))
				{
					char *msg;

					msg = (char *)AllocMemory(60+strlen(tmp),TRUE);
					sprintf(msg,"Can't find  \"%s\"\n in MainFile generated by GenCodeC\n\n",tmp);
					DisplayMsg(msg);
					FreeMemory(msg);
					FreeMemory(tmp);

					return NULL;
				}
				str1+=strlen(tmp);
				ctmp=*str1;
				*str1='\0';
				fprintf(file,"\t\t\t%s\n\n",str);
				*str1=ctmp;
			}
			else
			{
				/* Write NEW IDCMP */
				fprintf(file,"\t\t\tcase %s:\n",name);
				fprintf(file,"\t\t\t/* end of case %s */\n\n",name);
			}
		}
		FreeMemory(tmp);
	}

	if (OldMainExists)
		return buf;
	else
		return (char *)TRUE;
}

/****************************************************************************************************************/
/*****																										*****/
/**								 				WriteIncludes												   **/
/*****																										*****/
/****************************************************************************************************************/

static char *WriteIncludes(FILE *file,char *adr_file,char *HeaderFile,char *MainFile,BOOL OldMainExists)
{
	if (!OldMainExists)
	{
		fprintf(file,"\n/* Include generated by GenCodeC */\n");
		fprintf(file,"#include \"%s\"\n\n",FilePart(HeaderFile));

		return NULL;
	}
	else
	{
		return CopyBlock(file,adr_file,adr_file,HEADER_END,LIBRARY_DECLARATION,
						HEADER_END_MSG,LIBRARY_DECLARATION_MSG,MainFile);
	}
}

/****************************************************************************************************************/
/*****																										*****/
/**								 				WriteDeclarations											   **/
/*****																										*****/
/****************************************************************************************************************/

static char *WriteDeclarations(FILE *file,char *adr_file,char *str,char *MainFile,BOOL OldMainExists,BOOL Locale)
{
	if (!OldMainExists)
	{
		fprintf(file,LIBRARY_DECLARATION);
		fprintf(file,"#ifdef SASC\n");
		fprintf(file,"extern struct Library * IntuitionBase;\n");
		fprintf(file,"#else\n");
		fprintf(file,"struct Library * IntuitionBase;\n");
		fprintf(file,"#endif\n");
		fprintf(file,LIBRARY_MUI);
		if (Locale)
				fprintf(file,LIBRARY_LOCALE);

		return NULL;
	}
	else
	{
		fprintf(file,"%s",LIBRARY_DECLARATION);
		str = CopyBlock(file,adr_file,str,LIBRARY_DECLARATION,LIBRARY_MUI,
						LIBRARY_DECLARATION_MSG,LIBRARY_MUI_MSG,MainFile);
		fprintf(file,"%s",LIBRARY_MUI);
		if (Locale && (!strstr(str,LIBRARY_LOCALE)))
		{
			fprintf(file,"%s",LIBRARY_LOCALE);
			str = CopyBlock(file,adr_file,str,LIBRARY_MUI,INIT_BEGIN,
							LIBRARY_MUI_MSG,INIT_BEGIN_MSG,MainFile);
		}
		else
		{
			if (!Locale && (strstr(str,LIBRARY_LOCALE)))
				str = CopyBlock(file,adr_file,str,LIBRARY_LOCALE,INIT_BEGIN,
								LIBRARY_LOCALE_MSG,INIT_BEGIN_MSG,MainFile);
			else
				str = CopyBlock(file,adr_file,str,LIBRARY_MUI,INIT_BEGIN,
								LIBRARY_MUI_MSG,INIT_BEGIN_MSG,MainFile);
		}
		return str;
	}
}

/****************************************************************************************************************/
/*****																										*****/
/**								 			WriteInitFunction												   **/
/*****																										*****/
/****************************************************************************************************************/

static char *WriteInitFunction(FILE *file,char *adr_file,char *str,char *MainFile,BOOL OldMainExists,BOOL Locale)
{
	if (!OldMainExists)
	{
		fprintf(file,INIT_BEGIN);
		fprintf(file,"void init( void )\n");
		fprintf(file,"{\n");
		fprintf(file,"\tif (!(IntuitionBase = OpenLibrary(\"intuition.library\",37)))\n");
		fprintf(file,"\t{\n");
		fprintf(file,"\t\tprintf(\"Can't Open Intuition Library\\n\");\n");
		fprintf(file,"\t\texit(20);\n");
		fprintf(file,"\t}\n");
		fprintf(file,"\tif (!(MUIMasterBase = OpenLibrary(MUIMASTER_NAME,MUIMASTER_VMIN)))\n");
		fprintf(file,"\t{\n");
		fprintf(file,"\t\tprintf(\"Can't Open MUIMaster Library\\n\");\n");
		fprintf(file,"\t\tCloseLibrary(IntuitionBase);\n");
		fprintf(file,"\t\texit(20);\n");
		fprintf(file,"\t}\n");
		if (Locale)
		{
			fprintf(file,"%s",OPEN_LOCALE_LIBRARY);
			fprintf(file,"\t{\n");
			fprintf(file,"\t\tprintf(\"Can't Open Locale Library\\n\");\n");
			fprintf(file,"\t\tprintf(\"Built-in Language will be used !!!\\n\");\n");
			fprintf(file,"\t}\n");
			fprintf(file,"\tOpenAppCatalog(NULL,NULL);\n");
		}
		fprintf(file,INIT_END);

		return NULL;
	}
	else
	{
		fprintf(file,INIT_BEGIN);
		if (Locale && !(strstr(str,OPEN_LOCALE_LIBRARY)))
		{
			str = CopyBlock(file,adr_file,str,INIT_BEGIN,INIT_END,
							INIT_BEGIN_MSG,INIT_END_MSG,MainFile);
			fprintf(file,"%s",OPEN_LOCALE_LIBRARY);
			fprintf(file,"\t{\n");
			fprintf(file,"\t\tprintf(\"Can't Open Locale Library\\n\");\n");
			fprintf(file,"\t\tprintf(\"Built-in Language will be used !!!\\n\");\n");
			fprintf(file,"\t}\n");
			fprintf(file,"\tOpenAppCatalog(NULL,NULL);\n");
		}
		else
		{
			if (!Locale && (strstr(str,OPEN_LOCALE_LIBRARY)))
			{
				str = CopyBlock(file,adr_file,str,INIT_BEGIN,OPEN_LOCALE_LIBRARY,
								INIT_BEGIN_MSG,OPEN_LOCALE_LIBRARY_MSG,MainFile);
				str = CopyBlock(file,adr_file,str,OPEN_CATALOG,INIT_END,
								OPEN_CATALOG_MSG,INIT_END_MSG,MainFile);
			}
			else
			{
				str = CopyBlock(file,adr_file,str,INIT_BEGIN,INIT_END,
								INIT_BEGIN_MSG,INIT_END_MSG,MainFile);
			}
		}
		fprintf(file,INIT_END);

		return str;
	}
}

/****************************************************************************************************************/
/*****																										*****/
/**								 			WriteEndFunction												   **/
/*****																										*****/
/****************************************************************************************************************/

static char *WriteEndFunction(FILE *file,char *adr_file,char *str,char *MainFile,BOOL OldMainExists,BOOL Locale)
{
	if (!OldMainExists)
	{
		fprintf(file,END_BEGIN);
		fprintf(file,"void end( void )\n{\n");
		if (Locale)
		{
			fprintf(file,"%s",CLOSE_CATALOG);
			fprintf(file,"\tif (LocaleBase)\n");
			fprintf(file,"\t\t%s",CLOSE_LOCALE_LIBRARY);
		}
		fprintf(file,"\tCloseLibrary(MUIMasterBase);\n");
		fprintf(file,"\tCloseLibrary(IntuitionBase);\n");
		fprintf(file,"\texit(20);\n");
		fprintf(file,END_END);
		fprintf(file,"\n");

		return NULL;
	}
	else
	{
		fprintf(file,END_BEGIN);
		if (Locale && !(strstr(str,CLOSE_CATALOG)))
		{
			str = CopyBlock(file,adr_file,str,END_BEGIN,CLOSE_LIBRARY,
							END_BEGIN_MSG,CLOSE_LIBRARY_MSG,MainFile);
			fprintf(file,"%s",CLOSE_CATALOG);
			fprintf(file,"\tif (LocaleBase)\n");
			fprintf(file,"\t\t%s",CLOSE_LOCALE_LIBRARY);
			fprintf(file,"%s",CLOSE_LIBRARY);
			str = CopyBlock(file,adr_file,str,CLOSE_LIBRARY,END_END,
							CLOSE_LIBRARY_MSG,END_END_MSG,MainFile);
		}
		else
		{
			if (!Locale && (strstr(str,CLOSE_CATALOG)))
			{
				str = CopyBlock(file,adr_file,str,END_BEGIN,CLOSE_CATALOG,
								END_BEGIN_MSG,CLOSE_CATALOG_MSG,MainFile);
				str = CopyBlock(file,adr_file,str,CLOSE_LOCALE_LIBRARY,END_END,
								CLOSE_LOCALE_LIBRARY_MSG,END_END_MSG,MainFile);
			}
			else
			{
				str = CopyBlock(file,adr_file,str,END_BEGIN,END_END,
								END_BEGIN_MSG,END_END_MSG,MainFile);
			}
		}
		fprintf(file,END_END);

		return str;
	}
}

/****************************************************************************************************************/
/*****																										*****/
/**								 			WriteMainFunction												   **/
/*****																										*****/
/****************************************************************************************************************/

static void WriteMainFunction(FILE *file,char *adr_file,char *str,char *MainFile,char *name,
							  BOOL OldMainExists,ULONG varnb)
{
	if (!OldMainExists)
	{
		fprintf(file,"/* Main Function inserted by GenCodeC */\n");
		fprintf(file,"int main(int argc,char **argv)\n");
		fprintf(file,"{\n");
		fprintf(file,"\tstruct Obj%s * %s = NULL;	/* Object */\n",name,name);
		fprintf(file,"\tBOOL\trunning = TRUE;\n");
		fprintf(file,"\tULONG\tsignal;\n\n");
		fprintf(file,"\t/* Program initialisation : generated by GenCodeC */\n");
		fprintf(file,"\tinit();\n\n");
		fprintf(file,"\t/* Create Object : generated by GenCodeC */\n");
		fprintf(file,"\tif (!(%s = Create%s()))\n",name,name);
		fprintf(file,"\t{\n");
		fprintf(file,"\t\tprintf(\"Can't Create %s\\n\");\n",name);
		fprintf(file,"\t\tend();\n");
		fprintf(file,"\t}\n\n");
		fprintf(file,"\twhile (running)\n");
		fprintf(file,"\t{\n");
		fprintf(file,"\t\tswitch (DoMethod(%s->%s,MUIM_Application_Input,&signal))\n",name,name);
		fprintf(file,"\t\t{\n");
		fprintf(file,"\t\t\tcase MUIV_Application_ReturnID_Quit:\n");
		fprintf(file,"\t\t\t\trunning = FALSE;\n");
		fprintf(file,"\t\t\t\tbreak;\n\n");
		fprintf(file,"\t\t\t%s",CASE_BEGIN);
	}
	else
	{
		str = CopyBlock(file,adr_file,str,END_END,CASE_BEGIN,
						END_END_MSG,CASE_BEGIN_MSG,MainFile);
		fprintf(file,CASE_BEGIN);
	}

	if (!(str = WriteIDCMP(file,str,varnb,OldMainExists)))
		return;

	if (!OldMainExists)
	{
		fprintf(file,"\t\t\t/* End computing of IDCMP */\n\n");
		fprintf(file,"\t\t\tdefault:\n");
		fprintf(file,"\t\t\t\tbreak;\n");
		fprintf(file,"\t\t}\n");
		fprintf(file,"\t\tif (running && signal) Wait(signal);\n");
		fprintf(file,"\t}\n");
		fprintf(file,"\tDispose%s(%s);\n",name,name);
		fprintf(file,"\tend();\n");
		fprintf(file,"}\n");
	}
	else
	{
		fprintf(file,"\t\t\t%s",CASE_END);
		CopyBlock(file,adr_file,str,CASE_END,NULL,
				  CASE_END_MSG,NULL,MainFile);
	}
}

/****************************************************************************************************************/
/*****																										*****/
/**								 			WriteMainFile													   **/
/*****																										*****/
/****************************************************************************************************************/

void WriteMainFile(char *HeaderFile,char *MainFile,char *MainHeaderText,ULONG varnb,BOOL Locale)
{
	BPTR	BakFile;
	char	*adr_file = NULL;
	char	*str;
	char	*buffer	 = NULL;
	char	*name = NULL;
	BOOL	OldMainExists = FALSE;
	FILE	*file;


	/* If the file already exists, we load it in memory and we save it in a .bak file*/
	if (adr_file = LoadFileInRAM(MainFile,FALSE))
	{
		OldMainExists = TRUE;
		buffer = AllocMemory(strlen(MainFile)+4+1,TRUE);
		strcpy(buffer,MainFile);
		strcat(buffer,".bak");
		if (BakFile = OpenFile(buffer,MODE_NEWFILE,FALSE))
		{
			FWrite(BakFile,adr_file,strlen(adr_file),1);
			CloseFile(BakFile);
		}
		else
		{
			DisplayMsg("Can't create a backup of your Main file !!! \n");
		}
		FreeMemory(buffer);
	}

	MB_GetVarInfo(0, MUIB_VarName, &name, TAG_END);

	if (file = fopenFile(MainFile,"w",FALSE))
	{
		fprintf(file,"/* Main-Header File inserted by GenCodeC */\n");

		/* Copy Main-Header into MainFile */
		fprintf(file,"%s",MainHeaderText);

		fprintf(file,HEADER_END);

		str = WriteIncludes(file,adr_file,HeaderFile,MainFile,OldMainExists);

		str = WriteDeclarations(file,adr_file,str,MainFile,OldMainExists,Locale);

		str = WriteInitFunction(file,adr_file,str,MainFile,OldMainExists,Locale);

		if (OldMainExists)
			str = CopyBlock(file,adr_file,str,INIT_END,END_BEGIN,
							INIT_END_MSG,END_BEGIN_MSG,MainFile);

		str = WriteEndFunction(file,adr_file,str,MainFile,OldMainExists,Locale);

		WriteMainFunction(file,adr_file,str,MainFile,name,OldMainExists,varnb);

		fcloseFile(file);
		FreeMemory(adr_file);
	}
	else
	{
		DisplayMsg("Unable to create Main file !\n");
		FreeMemory(adr_file);
	}
}
