#include "ebase.h"
#include "../tk_base.h"

using namespace event;
using namespace std;

EBase::t_bind_table EBase::bindTable;

EBase::EBase(const char* eventType,const EField* eventFields[]):eventType(eventType),eventFields(eventFields)
{
	widget=0;
	anyListenerRegistred=false;

	fieldsLength=0;
	while(*eventFields[fieldsLength]!=EField::END)
		fieldsLength++;
	bindTable[guid.getId()]=this;
}

EBase::~EBase()
{
	bindTable.erase(guid.getId());
}

int EBase::handleEvent(ClientData clientData,Tcl_Interp* interp,int objc,Tcl_Obj* CONST objv[])
{
	if (objc==1)
	{
		Tcl_WrongNumArgs(interp,objc,objv,0);
		return TCL_ERROR;
	}

	char* guid=Tcl_GetString(objv[1]);
	EBase* event=getEventById(guid);
	if (!event->widget->isEventsEnabled()) return TCL_OK;

	if (event==0) return TCL_ERROR;

	if (objc!=event->fieldsLength+2)
	{
		Tcl_WrongNumArgs(interp,objc,objv,0);
		return TCL_ERROR;
	}

	EHeader header;
	int value;

	Tcl_GetIntFromObj(interp,objv[2],&header.serial);
	header.id=Tcl_GetString(objv[3]);
	Tcl_GetIntFromObj(interp,objv[4],&header.time);
	header.root=Tcl_GetString(objv[5]);
	header.subwindow=Tcl_GetString(objv[6]);
	header.type=Tcl_GetString(objv[7]);
	header.widget=Tcl_GetString(objv[8]);
	Tcl_GetBooleanFromObj(interp,objv[9],&value);
	header.sendevent=(value!=0);

	header.source=event->widget;

	return event->preprocessEvent(header,interp,objc,objv);
}

EBase* EBase::getEventById(const string& id)
{
	t_bind_table::const_iterator it=bindTable.find(id);
	if (it==bindTable.end()) return 0;

	return it->second;
}

void EBase::createBind(TclInterp* interp,Tk_Uid widgetName)
{
	string str=string("bind ")+widgetName+" <"+eventType+"> {onevent \""+guid.getId()+"\" ";
	for(int i=0;i<fieldsLength;i++)
	{
		const EField& field=*eventFields[i];
		str.push_back('%');
		str.push_back(field.getId());
		str.push_back(' ');
	}
	str.push_back('}');
	interp->eval(str);
}

void EBase::afterListenerRegistred()
{
    anyListenerRegistred=true;
	if (widget==0) return;
	bind(widget);
}

void EBase::bind(TkBase* widget)
{
	this->widget=widget;
	if (anyListenerRegistred) createBind(widget->getInterp(),widget->getUid());
}

