#include <libraries/mui.h> 
#include <clib/alib_protos.h>
#include <clib/muimaster_protos.h>
#include <clib/dos_protos.h>
#include <pragma/muimaster_lib.h>
#include <clib/exec_protos.h>
#include <exec/types.h>
#include <libraries/dosextens.h>
#include <mui/nlistview_mcc.h>

#include "poetout.h"
#include "poetgui.h"
#include "wordset.h"
#include "misc/filereq.h"
#include "output.h"

// Need to open a console window and redirect stdout to it!

PoetOutput::PoetOutput(){
	oa_SetName("Poet Output");
	oa_Author="T.Miles";
	oa_Version="1.0";
	oa_Date="22/03/2000";
	op_Type=MAKE_TYPE('P','O');
	o_useRenderer=FALSE;
	newConOut=NULL;
	TrackTable=NULL;
}

PoetOutput::~PoetOutput(){
	UINT size=wSets.GetSize();
	WordSet *pWd;
	
	if (TrackTable)
		delete[] TrackTable;
	while(size!=0){
		pWd=wSets.GetItem(0);
		delete pWd;
		wSets.DeleteItem(0);
		size--;
	}
	
	if (newConOut)
		Close(newConOut);
}	

BOOL PoetOutput::StartUp(){
	return OmegaOutput::StartUp();
}

void PoetOutput::SetTracks(){
	UINT trks;
	char buffer[256];;
	UINT sets=wSets.GetSize();
	WordSet *pWS;
	UINT f,n, totTrks=0;
	
	if (TrackTable)
		delete[] TrackTable;
		
	ClearTracks();	
	// Find out how many tracks we've got in total
	for (f=0;f<sets;f++){
		pWS=wSets.GetItem(f);
		totTrks+=pWS->GetTracks();
	}
	// Allocate enough space
	TrackTable=new TableEntry[totTrks];
	totTrks=0;
	
	AddTrackName("LineFeed");
	for (f=0;f<sets;f++){
		pWS=wSets.GetItem(f);
		trks=pWS->GetTracks();
		for (n=0;n<trks;n++){
			// Set the trackarray to point at the correct wordset - this acts as
			// LookUp table later on! 
			TrackTable[totTrks].te_set=f;
			TrackTable[totTrks].te_offset=n;		
			printf("Table Entry: %d Set: %d Track: %d\n",totTrks,f,n);
			sprintf(&buffer[0],"Set_%d_Trk_%d",f,n);
			AddTrackName(&buffer[0]);
			totTrks++;
		}
	}
}

void PoetOutput::OnConfig(){
	char *tempName;
	char *baseFile=NULL;
	BOOL loop=TRUE;
	ULONG val,id,gui_Sig=0;
	UINT len,n;
	FileReq myReq;
	FILE *file;
	WordSet *newWS;
	
	SetAttrs(bt_conclose,MUIA_Disabled,!newConOut);
	
	gui_OpenWin();

	while(loop){
		id=DoMethod((Object *)app, MUIM_Application_NewInput, &gui_Sig);
		switch (id){
		case ID_USE:
		case ID_CANCEL:
			loop=FALSE;
			break;

		case ID_SAVE:
			if (file=OpenConfigFile(TRUE,TRUE)){
				OnSaveConfig(file);
				fclose(file);
			}
			break;
		case ID_LOAD:
			if (file=OpenConfigFile(TRUE,FALSE)){
				// Need to free the sets already loaded
				DoMethod((Object *)lv_wordsets,MUIM_List_Clear);
				for (n=0;n<wSets.GetSize();n++){
					newWS=wSets.GetItem(0);
					newWS->ClearSet();
					delete newWS;
					wSets.DeleteItem(0);
				}
				OnLoadConfig(file);
				fclose(file);
			}
			break;

		case ID_FILE:
			myReq.CreateRequester("Select Dictionary File",NULL,NULL,"#?.dic",FALSE,FALSE);	
			// Copy the filename into storage
			tempName=myReq.GetName();
			if (!myReq.Cancelled()){
				if (baseFile)
					delete[]baseFile;
				len=strlen(tempName);
				baseFile=new char[len+1];
				strncpy(baseFile, tempName,len);
				baseFile[len]=NULL;
				DoMethod((Object *)lv_wordsets,MUIM_List_InsertSingle,(APTR)baseFile,MUIV_List_Insert_Bottom);
				newWS=new WordSet;
				if(newWS->LoadSet(baseFile)){
					wSets.AddItem(newWS);
					op_Configured=TRUE;
				}		
			}
			break;
		case ID_CONCLOSE:
			if (newConOut){
				Close(newConOut);
				SetAttrs(bt_conclose,MUIA_Disabled,TRUE);
				newConOut=NULL;
			}
			break;
		case ID_REMOVE:
			GetAttr(MUIA_NList_Active,lv_wordsets,&val);
			if (val!=-1){
				wSets.DeleteItem(val);
				DoMethod((Object *)lv_wordsets,MUIM_NList_Remove,val);
				if (wSets.GetSize()==0)
					op_Configured=FALSE;
			}
			else
				Error("Can't Delete Track","Select Track From List");
			break;
		}
		if (loop && gui_Sig)
			Wait(gui_Sig);		
	}
	SetTracks();	
	gui_CloseWin();
	delete[]baseFile;
}

void PoetOutput::OnSaveConfig(FILE *f){
	ULONG entries;
	char *file=NULL;

	OmegaOutput::OnSaveConfig(f);	
	GetAttr(MUIA_NList_Entries,lv_wordsets,&entries);
	
	for (UINT n=0;n<entries;n++){
		DoMethod((Object *)lv_wordsets,MUIM_NList_GetEntry,n,&file);	
		fprintf(f,"%%\n%s\n",file);
	}
}

void PoetOutput::OnLoadConfig(FILE *f){
	char *file=new char[255];
	char tag;
	WordSet *newWS;
	
	OmegaOutput::OnLoadConfig(f);
	while (!(feof(f))){
		tag=fgetc(f);
		if (tag=='%' && fscanf(f,"%s",file)==1){
			DoMethod((Object *)lv_wordsets,MUIM_NList_InsertSingle,(APTR)file,MUIV_List_Insert_Bottom);
			newWS=new WordSet;
			if (newWS){
				if(newWS->LoadSet(file)){
					wSets.AddItem(newWS);
					op_Configured=TRUE;
				}
				else
					delete newWS;
			}
		}
	}
	delete[] file;
	SetTracks();
}

// Need to load in the wordsets again, as running the module
// will have deleted some words from the lists
void PoetOutput::OnStop(){
	ULONG size=wSets.GetSize();
	ULONG file,n;
	
	WordSet *pSet;
	
	// Clear the remains of the old sets
	for(n=0;n<size;n++){
		pSet=wSets.GetItem(0);
		pSet->ClearSet();
		delete pSet;
		wSets.DeleteItem(0);
	}
	// Load in the new
	for (n=0;n<size;n++){
		DoMethod((Object *)lv_wordsets,MUIM_NList_GetEntry,n,&file);
		if (file){
			pSet=new WordSet;
			if (pSet){
				pSet->LoadSet((char *)file);
				wSets.AddItem(pSet);
			}
		}
	}
}

// Pick the word from the list at the value'th position
// We can only get a possible 256 values so we've divided these into 
// seperate tracks
void PoetOutput::DrawNextFrame(UINT trk){
	UINT value, set,offset, word;
	char buffer[256];
	WordSet *pWS;
	Reference *pRef;
	set=TrackTable[trk-1].te_set;
	offset=TrackTable[trk-1].te_offset;
	word=offset*255+value;
	
	if (trk==0)
		Print("\n");
	else{
		value=o_GetCurrentValue(trk);
		pWS=wSets.GetItem(set);
		pRef=pWS->GetRef(word);
		if (pRef){
			pWS->RemoveRef(word);
			sprintf(&buffer[0],"%s ",pRef->ref_Word);
			Print(&buffer[0]);
		}
	}
}

void PoetOutput::InitialConfig(){
	FILE *file;
	
	if (file=OpenConfigFile(FALSE,FALSE)){
		OnLoadConfig(file);
		fclose(file);
	}
}

void PoetOutput::OnStart(){
	if (!newConOut)
		newConOut=Open("CON:0/0/500/500/Project Omega Poem Output",MODE_NEWFILE);
}

void PoetOutput::Print(char *string){
	UINT len=strlen(string);
	if (newConOut)
		Write(newConOut,string,len);
}
