#include <exec/types.h>
#include <intuition/gadgetclass.h>
#include <datatypes/soundclass.h>
#include <workbench/workbench.h>
#include <libraries/gadtools.h>
#include <libraries/iffparse.h>
#include <workbench/startup.h>
#include <graphics/gfxbase.h>
#include <exec/libraries.h>
#include <libraries/asl.h>
#include <exec/memory.h>
#include <string.h>
#include <stdio.h>
#include "SVXTool.h"

#include <proto/intuition.h>
#include <proto/gadtools.h>
#include <proto/iffparse.h>
#include <proto/exec.h>
#include <proto/icon.h>
#include <proto/dos.h>
#include <proto/asl.h>
#include <proto/wb.h>

#define MINLIB				40

struct IntuitionBase		*IntuitionBase;
struct Library				*WorkbenchBase;
struct GfxBase				*GfxBase;
struct Library				*GadToolsBase;
struct Library				*UtilityBase;
struct Library				*IconBase;
struct Library				*IFFParseBase;
struct Library				*AslBase;
struct VoiceHeader		Current;
struct FileRequester		*FReq;

UBYTE *Data;
char	WorkInputFile[256],WorkInputName[31],memtype;
int	WorkInputLen,WorkInputSPS;

extern void NotifyofError(char *bodytxt);
extern BOOL ReadInputFile(void);

void main(void)
{
	struct MsgPort			*wbport;
	struct AppWindow		*ApW;
	struct AppMessage		*A;

	ULONG sig,isig,wsig;

	memtype=0;
	Data=NULL;
	if(!(IntuitionBase	=(struct IntuitionBase *)	OpenLibrary("intuition.library",MINLIB)))
		NotifyofError("Could not open intuition.library v40+!");
	if(!(WorkbenchBase	=									OpenLibrary("workbench.library",MINLIB)))
		NotifyofError("Could not open workbench.library v40+!");
	if(!(GfxBase			=(struct GfxBase *)			OpenLibrary("graphics.library",MINLIB)))
		NotifyofError("Could not open graphics.library v40+!");
	if(!(IconBase			=									OpenLibrary("icon.library",MINLIB)))
		NotifyofError("Could not open icon.library v40+!");
	if(!(GadToolsBase	=									OpenLibrary("gadtools.library",MINLIB)))
		NotifyofError("Could not open gadtools.library v40+!");
	if(!(UtilityBase		=									OpenLibrary("utility.library",MINLIB)))
		NotifyofError("Could not open utility.library v40+!");
	if(!(IFFParseBase		=									OpenLibrary("iffparse.library",MINLIB)))
		NotifyofError("Could not open iffparse.library v40+!");
	if(!(wbport=CreateMsgPort()))
		NotifyofError("Could not open a message port\nto the Workbench!");
	if(!(AslBase			=									OpenLibrary("asl.library",MINLIB)))
		NotifyofError("Could not open asl.library v40+!");
	if(IntuitionBase&&WorkbenchBase&&GfxBase&&IconBase&&GadToolsBase&&UtilityBase&&AslBase&&wbport)
		if(!SetupScreen())
		{
			if(!OpenSVXTool_MainWindow())
			{
				if(ApW=AddAppWindow(0,0,SVXTool_MainWnd,wbport,NULL))
				{
					if(FReq=AllocAslRequestTags(ASL_FileRequest,
						ASL_OKText,"Open",ASLFR_Window,SVXTool_MainWnd,
						ASLFR_SleepWindow,TRUE,ASLFR_RejectIcons,TRUE,
						TAG_END))
					{
						BOOL go=TRUE;

						isig=1L<<SVXTool_MainWnd->UserPort->mp_SigBit;
						wsig=1L<<wbport->mp_SigBit;

						while(go)
						{
							sig=Wait(isig|wsig);
							if(sig&isig)
								go=HandleSVXTool_MainIDCMP();
							if(sig&wsig)
								while(A=(struct AppMessage *)GetMsg(wbport))
								{
									struct AppMessage		AMsg;
									struct WBArg			*argp;

									CopyMem((char *)A,(char *)&AMsg,(long)sizeof(struct AppMessage));
									argp=AMsg.am_ArgList;
									NameFromLock(argp->wa_Lock,WorkInputFile,255);
									strcpy(WorkInputName,(char *)argp->wa_Name);
									AddPart(WorkInputFile,WorkInputName,255);
									ReplyMsg((struct Message *)A);
//									GT_SetGadgetAttrs(SVXTool_MainGadgets[GDX_Hear_BTN],SVXTool_MainWnd,NULL,GA_Disabled,FALSE,TAG_END);
//									GT_SetGadgetAttrs(SVXTool_MainGadgets[GDX_Convert_BTN],SVXTool_MainWnd,NULL,GA_Disabled,FALSE,TAG_END);
//									GT_SetGadgetAttrs(SVXTool_MainGadgets[GDX_SymbolName_STR],SVXTool_MainWnd,NULL,GA_Disabled,FALSE,TAG_END);
//									GT_SetGadgetAttrs(SVXTool_MainGadgets[GDX_memtype_CYC],SVXTool_MainWnd,NULL,GA_Disabled,FALSE,TAG_END);
									ReadInputFile();
								}
						}
						FreeAslRequest(FReq);
					}
					else
						NotifyofError("Could not allocate file request structure.");
					RemoveAppWindow(ApW);
				}
				else
					NotifyofError("Could not set up AppWindow.");
			}
			else
				NotifyofError("Could not open window.");
			CloseSVXTool_MainWindow();
		}
		else
			NotifyofError("Could not set up screen.");
		CloseDownScreen();
	if(Data)
		FreeVec(Data);
	if(wbport)
	{
		struct Message *msg;

		while(msg=GetMsg(wbport))
			ReplyMsg(msg);
		DeleteMsgPort(wbport);
	}
	if(IntuitionBase)
		CloseLibrary((struct Library *)IntuitionBase);
	if(WorkbenchBase)
		CloseLibrary(WorkbenchBase);
	if(GfxBase)
		CloseLibrary((struct Library *)GfxBase);
	if(IconBase)
		CloseLibrary((struct Library *)IconBase);
	if(GadToolsBase)
		CloseLibrary(GadToolsBase);
	if(UtilityBase)
		CloseLibrary(UtilityBase);
	if(IFFParseBase)
		CloseLibrary(IFFParseBase);
	if(AslBase)
		CloseLibrary(AslBase);
}

void NotifyofError(char *bodytxt)
{
	struct EasyStruct errorES =
	{
		sizeof(struct EasyStruct),0,
		"SVXTool Message",
		NULL,"Understood"
	};

	errorES.es_TextFormat=bodytxt;
	EasyRequestArgs(SVXTool_MainWnd,&errorES,NULL,NULL);
}

BOOL ReadInputFile(void)
{
	BOOL success=FALSE;
	struct DiskObject	*dobj;
	struct IFFHandle 	*iff;

	if(dobj=GetDiskObjectNew(WorkInputFile))
	{
		ULONG FX,FY;

		Forbid();
		FX=GfxBase->DefaultFont->tf_XSize;
		FY=GfxBase->DefaultFont->tf_YSize;
		Permit();
		if(iff=AllocIFF())
		{
			if(iff->iff_Stream=Open(WorkInputFile,MODE_OLDFILE))
			{
				long error;

				InitIFFasDOS(iff);
				if(!(error=OpenIFF(iff,IFFF_READ)))
				{
					BOOL v=FALSE,b=FALSE;
					struct ContextNode *cn;

					while(!error)
					{
						while((error=ParseIFF(iff,IFFPARSE_RAWSTEP))==IFFERR_EOC);
						if(!error)
						{
							cn=CurrentChunk(iff);
							if(cn->cn_ID==ID_VHDR)
							{
								v=TRUE;
								ReadChunkBytes(iff,&Current,cn->cn_Size);
								if(Current.vh_Compression)
									error=-13;
							}
							else if(cn->cn_ID==ID_BODY)
							{
								if(Data)
									FreeVec(Data);
								if(Data=AllocVec(cn->cn_Size,MEMF_CLEAR))
								{
									b=TRUE;
									ReadChunkBytes(iff,Data,cn->cn_Size);
									WorkInputLen=Current.vh_OneShotHiSamples+Current.vh_RepeatHiSamples;
									WorkInputSPS=Current.vh_SamplesPerSec;
									DrawImage(SVXTool_MainWnd->RPort,dobj->do_Gadget.GadgetRender,
									Scr->WBorLeft+(FX*13+3)/6,
									Scr->RastPort.TxHeight+Scr->WBorTop+1+(FY*21+4)/8);
									GT_SetGadgetAttrs(SVXTool_MainGadgets[GDX_Name_TXT],SVXTool_MainWnd,NULL,GTTX_Text,WorkInputName,TAG_END);
									GT_SetGadgetAttrs(SVXTool_MainGadgets[GDX_Length_NMB],SVXTool_MainWnd,NULL,GTNM_Number,WorkInputLen,TAG_END);
									GT_SetGadgetAttrs(SVXTool_MainGadgets[GDX_SamplesPerSec_NMB],SVXTool_MainWnd,NULL,GTNM_Number,WorkInputSPS,TAG_END);
									GT_SetGadgetAttrs(SVXTool_MainGadgets[GDX_Hear_BTN],SVXTool_MainWnd,NULL,GA_Disabled,FALSE,TAG_END);
									GT_SetGadgetAttrs(SVXTool_MainGadgets[GDX_Convert_BTN],SVXTool_MainWnd,NULL,GA_Disabled,FALSE,TAG_END);
									GT_SetGadgetAttrs(SVXTool_MainGadgets[GDX_SymbolName_STR],SVXTool_MainWnd,NULL,GA_Disabled,FALSE,TAG_END);
									GT_SetGadgetAttrs(SVXTool_MainGadgets[GDX_memtype_CYC],SVXTool_MainWnd,NULL,GA_Disabled,FALSE,TAG_END);
									success=TRUE;
								}
								else
									NotifyofError("Not enough memory to allocate work space.");
							}
						}
					}
					if(error==-1)
					{
						if(!b)
							NotifyofError("No body found in file.");
						else if(!v)
							NotifyofError("No VHDR found in file.");
					}
					CloseIFF(iff);
				}
				if(error<-1)
				{
					char *errmsg[]=
					{
						"End of file","End of context",
						"No lexical scope","Insufficient memory",
						"Stream read error","Stream write error",
						"Stream seek error","File is corrupt",
						"IFF syntax error","Not an IFF file",
						"Required call-back hook missing",
						"Return to client.","SVXTool does not currently handle\ncompressed samples."
					};

					NotifyofError(errmsg[-error-1]);
				}
				Close(iff->iff_Stream);
			}
			else
			{
				char msg[256];
					sprintf(msg,"Could not open file\n\"%s\".",WorkInputFile);
				NotifyofError(msg);
			}
			FreeIFF(iff);
		}
		else
			NotifyofError("Insufficient memory for AllocIFF().");
		FreeDiskObject(dobj);
	}
	else
	{
		char msg[256];

		sprintf(msg,"Trouble finding a disk object for\n\"%s\".",WorkInputFile);
		NotifyofError(msg);
	}
	return(success);
}