// EdScript.cpp: implementation of the EdScript class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "EdScript.h"
#include <Stuff\Stuff.hpp>
#include <GameOS\ToolOS.hpp>

using namespace Stuff;
#include <Adept\Adeptheaders.hpp>
#include <MW4\Vehicle.hpp>
#include <mw4\mwapplication.hpp>
#include <Adept\tool.hpp>
using namespace MechWarrior4;
using namespace Adept;

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

// Keywords
#define BLOCKDEDEFINE "UIFIELDS"
#define FIELDDEFINE	  "FIELD"
//
/*
UIFIELDS
{
FIELD<INT,Tag,Text,Defaultval>;
FIELD<FLOAT,Tag,Text,Defaultval>;
FIELD<TEXT,Tag,Text,"DefaultText">;
FIELD<STATICTEXT,"Text">;	
}

  int x=<Tag>
  float y=<Tag>
  
*/

EdScript::EdScript(CString fname)
{
	Init();
	LoadTemplate(fname);
}

EdScript::EdScript()
{
	Init();
}

bool EdScript::LoadTemplate(CString tempname)
{
	Environment.HookGetFile = Adept::Tool::GetFileForGOS;
	Environment.HookDoesFileExist = Adept::Tool::FindFileForGOS;

	TemplateName=tempname;
	
	CString fname;
	fname="Content\\ABLScripts\\GenericScripts\\"+TemplateName+".tpl";
	if(!gos_DoesFileExist(fname)) return false;
	FileStream file(fname);
	int size=file.GetBytesRemaining();
	char *sdat=new char[size+1];
	sdat[size]='\0';
	file.ReadBytes(sdat,size);
	CString str;
	str=sdat;
	delete sdat;
	str.Replace("\x0D\x0A","\n");
	SetTemplate(str);

	Environment.HookGetFile = Application::GetFileForGOS;
	Environment.HookDoesFileExist = Application::FindFileForGOS;
	return true;
}

void EdScript::SetTemplate(CString str)
{
	Template=str;
	if (Fields) {delete Fields; Fields=NULL;}
	
	TotFields=CountFieldsIn(Template);
	if(TotFields<0) PAUSE(("UIFIELD Syntax Error In Script"));
	if(TotFields==0) return;
	Fields=new ScriptField[TotFields];
	
	int fcount=0;
	
	int fcom=Template.Find(BLOCKDEDEFINE,0);
	int blockstart, blockend;
	
	blockstart=Template.Find('{',fcom);
	blockend=Template.Find('}',blockstart);
	
	int argend;
	CString arg[4];
	int pos=blockstart;
	do
	{
		pos=Template.Find(FIELDDEFINE,pos);
		if(pos>=0) 
		{
			pos=Template.Find('<',pos);
			argend=Template.Find(',',pos);
			if(pos<0 || argend<0) PAUSE(("UIFIELD Syntax Error In Script"));
			pos++;
			arg[0]=Template.Mid(pos,argend-pos);
			arg[0].TrimLeft();
			arg[0].TrimRight();
			
			int ststart,stend;
			if(!arg[0].Compare("STATICTEXT"))
			{
				pos=argend+1;
				ststart=Template.Find('\"',pos)+1;
				stend=Template.Find('\"',ststart);
				argend=Template.Find('>',stend);
				if(ststart<0 || stend<0) PAUSE(("UIFIELD Syntax Error In Script"));
				arg[1]=Template.Mid(ststart,stend-ststart);
				Fields[fcount].SetData(arg[1]);
			}
			else
			{
				pos=argend+1;
				argend=Template.Find(',',pos);
				if(pos<0 || argend<0) PAUSE(("UIFIELD Syntax Error In Script"));
				arg[1]=Template.Mid(pos,argend-pos);
				arg[1].TrimLeft();
				arg[1].TrimRight();
				
				pos=argend+1;
				ststart=Template.Find('\"',pos)+1;
				stend=Template.Find('\"',ststart);
				argend=Template.Find(',',stend);
				if(pos<0 || argend<0) PAUSE(("UIFIELD Syntax Error In Script"));
				arg[2]=Template.Mid(ststart,stend-ststart);
				
				
				if(!arg[0].Compare("INT"))
				{
					pos=argend+1;
					argend=Template.Find('>',pos);
					if(pos<0 || argend<0) PAUSE(("UIFIELD Syntax Error In Script"));
					arg[3]=Template.Mid(pos,argend-pos);
					arg[3].TrimLeft();
					arg[3].TrimRight();
					
					Fields[fcount].SetData(arg[2],arg[1],atoi(arg[3]));
				}
				else if(!arg[0].Compare("FLOAT"))
				{
					pos=argend+1;
					argend=Template.Find('>',pos);
					if(pos<0 || argend<0) PAUSE(("UIFIELD Syntax Error In Script"));
					arg[3]=Template.Mid(pos,argend-pos);
					arg[3].TrimLeft();
					arg[3].TrimRight();
					
					Fields[fcount].SetData(arg[2],arg[1],(float)atof(arg[3]));
				}
				else if(!arg[0].Compare("TEXT"))
				{
					pos=argend+1;
					ststart=Template.Find('\"',pos)+1;
					stend=Template.Find('\"',ststart);
					argend=Template.Find('>',stend);
					if(pos<0 || argend<0) PAUSE(("UIFIELD Syntax Error In Script"));
					arg[3]=Template.Mid(ststart,stend-ststart);
					
					Fields[fcount].SetData(arg[2],arg[1],arg[3]);
				}
				else
				{
					CString str;
					str="UIFIELD Syntax Error In Script,Undefined Field Type ("+arg[0]+")";
					PAUSE((str));
				}
			}
			
			
			fcount++;
		}
	}
	while(pos<blockend && pos>=0);
	
	Template.Delete(fcom,(blockend-fcom)+1);	// Delete the FieldUI define block
	
}

int EdScript::CountFieldsIn(CString str)
{
	int fcom=Template.Find(BLOCKDEDEFINE,0);
	int blockstart, blockend;
	int count=0;
	
	if(fcom<0) return 0;
	
	blockstart=Template.Find('{',fcom);
	if(blockstart<0) return -1;
	blockend=Template.Find('}',blockstart);
	
	int pos=blockstart;
	do
	{
		pos=Template.Find(FIELDDEFINE,pos);
		if(pos>=0) {count++;pos+=strlen(FIELDDEFINE);}
	}
	while(pos<blockend && pos>=0);
	
	return count;
}


CString EdScript::GetScript()
{
	CString header,final;
	header="//TEMPLATENAME=<"+TemplateName+">\n";
	int i;
	
	final=Template;
	for(i=0;i<TotFields;i++)
	{
		Fields[i].AddDefaultValueLine(header);
		Fields[i].InsertValue(&final);
	}
	
	final=header+final;
	return final;
}

bool EdScript::GetDefaultValues(CString script)
{
	int pos,argend;
	pos=script.Find("//TEMPLATENAME=<");
	if(pos<0) return false;
	pos+=strlen("//TEMPLATENAME=<");
	argend=script.Find(">",pos);
	CString str=script.Mid(pos,argend-pos);
	if(str.CompareNoCase(TemplateName))	//If the template is different or unloaded change/load it now.
		if(!LoadTemplate(script.Mid(pos,argend-pos))) return false;	
		
		for(int i=0;i<TotFields;i++)
			Fields[i].GetDefaultValue(script);
		
		
		return true;
}

void EdScript::Copy(EdScript &scrpt)
{
	TemplateName=scrpt.TemplateName;
	TotFields=scrpt.TotFields;
	delete Fields;
	Fields=new ScriptField[TotFields];
	for(int i=0;i<TotFields;i++) Fields[i]=scrpt.Fields[i];
}

EdScript *EdScript::Clone()
{
	EdScript *newscript=new EdScript;
	newscript->Copy(*this);
	return newscript; 
}

EdScript::~EdScript()
{
	
}


//Fields

bool ScriptField::GetDefaultValue(CString script)
{
	CString sstr="//VALUE<"+Tag+",";
	int pos=script.Find(sstr);
	pos+=sstr.GetLength();
	int argend=script.Find('>',pos);
	if(pos<0) return false;
	CString arg=script.Mid(pos,argend-pos);
	
	switch(Type)
	{
	case TEXTDATA:
		arg.TrimLeft('\"');
		arg.TrimRight('\"');
		SetData(Name,Tag,arg);
		break;
		
	case INTDATA:
		SetData(Name,Tag,atoi(arg));
		break;
		
	case FLOATDATA:
		SetData(Name,Tag,(float)atof(arg));
		break;
	}
	return true;
}

void ScriptField::InsertValue(CString *tstr)
{
	int loc=0;
	
	CString str;
	switch(Type)
	{
	case INTDATA:
		Value.Format("%i",IntData);
		break;
		
	case FLOATDATA:
		Value.Format("%0.5f",FloatData);
		break;
	}
	
	tstr->Replace('<'+Tag+'>',Value);
	
}

void ScriptField::SetData(CString nme,CString tg,int val)
{
	Tag=tg;
	Name=nme;
	IntData=val;
	Type=INTDATA;
}

void ScriptField::SetData(CString nme,CString tg,float val)
{
	Tag=tg;
	Name=nme;
	FloatData=val;
	Type=FLOATDATA;
}

void ScriptField::AddDefaultValueLine(CString &str)
{
	CString tstr;
	switch(Type)
	{
	case TEXTDATA:
		tstr.Format("//VALUE<%s,\"%s\">\n",Tag,Value);
		break;
		
	case INTDATA:
		tstr.Format("//VALUE<%s,%i>\n",Tag,IntData);
		break;
		
	case FLOATDATA:
		tstr.Format("//VALUE<%s,%f>\n",Tag,FloatData);
		break;
	}
	str+=tstr;
	
}


