#ifndef __MODULE_TCL_H__
#define __MODULE_TCL_H__

#include <ascript.h>
#undef DLLEXPORT
#include <tcl.h>
#include <tk.h>
#include <setjmp.h>

AScript_BeginModule(tcl)

class Object_Interp;

//-----------------------------------------------------------------------------
// Handler declaration
//-----------------------------------------------------------------------------
class Handler {
private:
	Object_Interp *_pObjInterp;
	Object_Function *_pObjFunc;
	Signal _sig;
public:
	inline Handler(Object_Interp *pObjInterp, Object_Function *pObjFunc, Signal sig) :
					_pObjInterp(pObjInterp), _pObjFunc(pObjFunc), _sig(sig) {}
	~Handler();
	Value Eval(ValueList &valListArg);
	Value Eval(int argc, const char *argv[]);
	inline Object_Interp *GetInterpObj() { return _pObjInterp; }
	inline Signal &GetSignal() { return _sig; }
};

//-----------------------------------------------------------------------------
// Object_Interp declaration
//-----------------------------------------------------------------------------
AScript_DeclarePrivClass(Interp);

class Object_Interp : public Object {
public:
	struct EventPack {
		Tcl_Event ev;
		Tcl_Interp *interp;
		// call information
		int objc;
		Tcl_Obj **objv;
		Tcl_Condition *pCond;
		// return information
		int rtn;
		Tcl_Obj *objRtn;
	};
public:
	AScript_DeclareObjectAccessor(Interp)
private:
	Tcl_Interp *_interp;
	Tcl_ThreadId _thread_id;
	int _cntCreatedCommand;
	int _cntCreatedVariable;
	Tcl_ObjType *ObjType_boolean;
	Tcl_ObjType *ObjType_bytearray;
	Tcl_ObjType *ObjType_double;
	Tcl_ObjType *ObjType_int;
	Tcl_ObjType *ObjType_list;
	Tcl_ObjType *ObjType_string;
public:
	Object_Interp(Tcl_Interp *interp);
	inline Tcl_Interp *GetInterp() { return _interp; }
	virtual ~Object_Interp();
	virtual Object *Clone() const;
	virtual String ToString(Signal sig, bool exprFlag);
	Tcl_Obj *ConvToTclObj(Environment &env, Signal sig, const Value &value);
	Value ConvFromTclObj(Environment &env, Signal sig, Tcl_Obj *obj);
	Tcl_Obj **CreateTclObjArray(Environment &env, Signal sig,
										const ValueList &valList, int *pObjc);
	String NewCommandName();
	String NewVariableName();
	void ExitMainLoop();
	Value TclEval(Environment &env, Signal sig, const ValueList &valList);
	static void DeleteTclObjArray(int objc, Tcl_Obj **objv);
	static int CommandProc(ClientData clientData, Tcl_Interp *interp,
										int argc, const char *argv[]);
	static void CommandDeleteProc(ClientData clientData);
	static int TclThreadProc(Tcl_Event *ev, int flags);
	Value InvokeTclThread(Environment &env, Signal sig, const ValueList &valListArg);
};

//-----------------------------------------------------------------------------
// Object_Variable declaration
//-----------------------------------------------------------------------------
AScript_DeclarePrivClass(Variable);

class Object_Variable : public Object {
public:
	AScript_DeclareObjectAccessor(Variable)
private:
	Object_Interp *_pObjInterp;
	String _varName;
public:
	Object_Variable(Object_Interp *pObjInterp, const char *varName);
	inline Object_Interp *GetInterpObj() { return _pObjInterp; }
	inline const char *GetVarName() const { return _varName.c_str(); }
	virtual ~Object_Variable();
	virtual Object *Clone() const;
	virtual Value DoPropGet(Signal sig, const Symbol *pSymbol, bool &evaluatedFlag);
	virtual Value DoPropSet(Signal sig, const Symbol *pSymbol,
										const Value &value, bool &evaluatedFlag);
	virtual String ToString(Signal sig, bool exprFlag);
	bool Set(Environment &env, Signal sig, const Value &value);
	Value Get(Environment &env, Signal sig);
};

//-----------------------------------------------------------------------------
// Object_Timer declaration
//-----------------------------------------------------------------------------
AScript_DeclarePrivClass(Timer);

class Object_Timer : public Object {
public:
	AScript_DeclareObjectAccessor(Timer)
private:
	Object_Interp *_pObjInterp;
	bool _contFlag;
	int _cnt, _idx;
	int _msecCont;
	Tcl_TimerToken _token;
	std::auto_ptr<Handler> _pHandler;
public:
	Object_Timer(Object_Interp *pObjInterp);
	virtual ~Object_Timer();
	virtual Object *Clone() const;
	virtual String ToString(Signal sig, bool exprFlag);
	void Start(Signal sig, const Function *pFunc, int msec, int msecCont, int cnt);
	void Cancel();
	bool TimerProc();
	static void TimerProcStub(ClientData clientData);
};



}}

#endif
