#include "tcl_interp.h"

#include "gui/tk_menu.h"
#include "gui/tk_toplevel.h"
#include "gui/event/ebase.h"

const char* TclInterp::type="TclInterp";

const char* TclInterp::getType() const
{
	return type;
}

Ptr<TclInterp> TclInterp::defaultInterp;

int TclInterp::onMenuEvent(ClientData clientData,Tcl_Interp *interp,int objc, Tcl_Obj *CONST objv[])
{
	char* menuUid=Tcl_GetString(objv[1]);
	char* commandId=Tcl_GetString(objv[2]);

	TkMenu::getMenuById(atoi(menuUid))->fireMenuEvent(commandId);

	return TCL_OK;
}

int TclInterp::onDeleteWindow(ClientData clientData,Tcl_Interp *interp,int objc, Tcl_Obj *CONST objv[])
{
	char* topLevelGuid=Tcl_GetString(objv[1]);
    
	TkTopLevel* topLevel=TkTopLevel::getTopLevelByGuid(topLevelGuid);

	if (topLevel==0) return TCL_OK;
	
	topLevel->getWindowListener()->onDestroy(topLevel);

	return TCL_OK;
}

TclInterp::TclInterp(Tcl_Interp* interp,ostream& logstream):interp(interp),logstream(&logstream),logging(true)
{
	managedLog=false;
	Tcl_CreateObjCommand(interp,"onmenuevent",TclInterp::onMenuEvent,(ClientData)0,(Tcl_CmdDeleteProc*)0);
	Tcl_CreateObjCommand(interp,"onevent",event::EBase::handleEvent,(ClientData)0,(Tcl_CmdDeleteProc*)0);
	Tcl_CreateObjCommand(interp,"ondeletewindow",TclInterp::onDeleteWindow,(ClientData)0,(Tcl_CmdDeleteProc*)0);
}

TclInterp::TclInterp(Tcl_Interp* interp,const char* fileName):interp(interp),logging(true)
{
	managedLog=true;
	Tcl_CreateObjCommand(interp,"onmenuevent",TclInterp::onMenuEvent,(ClientData)0,(Tcl_CmdDeleteProc*)0);
	Tcl_CreateObjCommand(interp,"onevent",EBase::handleEvent,(ClientData)0,(Tcl_CmdDeleteProc*)0);
	Tcl_CreateObjCommand(interp,"ondeletewindow",TclInterp::onDeleteWindow,(ClientData)0,(Tcl_CmdDeleteProc*)0);

	logstream=new fstream();
	fstream& f=*((fstream*)logstream);
	f.open(fileName,ios::out);
	if (!f) throw new ExceptionIO(fileName,false);
}

int TclInterp::eval(const string& s) const
{
	int result=Tcl_Eval(interp,s.c_str());
	(*logstream)<<s;
	if (result==TCL_ERROR) 
	{
		(*logstream)<<" [TCL_ERROR]"<<endl;
		(*logstream)<<"Result : "<<getStrResult()<<endl;
	}
	else
	{
		if (result==TCL_OK) (*logstream)<<" [TCL_OK]"<<endl;
		else
		{
			(*logstream)<<" [UNDEFINED]"<<endl;
		}
	}
	logstream->flush();
	return result;
}

TclInterp::~TclInterp()
{
	logstream->flush();		
	if (managedLog) 
	{
		delete logstream;
	}
}

Tcl_Obj* TclInterp::getObjResult() const
{
	return Tcl_GetObjResult(interp);
}

bool TclInterp::isNullResult() const
{
	return (getObjResult()==0);
}

char* TclInterp::getStrResult() const
{
	return Tcl_GetString(getObjResult());
}

int TclInterp::getIntResult() const
{
	int intValue;
	
	Tcl_GetIntFromObj(interp,getObjResult(),&intValue);

	return intValue;
}

string& TclInterp::getCodeName(int retCode)
{
	switch(retCode)
	{
		case TCL_OK:
			return *(new string("TCL_OK"));
		case TCL_ERROR:
			return *(new string("TCL_ERROR"));
		default:
			return *(new string("UNDEFINED"));
	}
}

