/* -----------------------------------------------------------------------------
	GSFramework
	Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */


#ifndef	__SCRIPTVMINTERFACE__
#define	__SCRIPTVMINTERFACE__


		#include "script/script_binding_interface.h"
		#include "http/http_interface.h"
		#include "network/network_interface.h"
		#include "memory/nshared_ptr.h"


namespace GS {
	namespace Script {
		struct Variant;
		class Object;

/*
	@short	Script virtual machine abstract interface.
	@author	Emmanuel Julien (ejulien@gsworks.fr)
*/
class	IVM : public SharedObject
{
public:

enum	State
{
	StateOk				=	0,
	StateExceptionThrown,		///< Crashed and open for inspection.
	StateDead					///< Crashed with no hope for inspection.
};

struct	IDebug
{
		/// Handle a runtime debug step.
virtual	void		OnStep(char type, const char *source, int line, const char *funcname) = 0;
		/// Handle a VM kill event.
virtual	void		OnFatalError(const char *reason) = 0;
		/// Handle a compiler error.
virtual	void		OnCompilerError(const char *error, const char *source, int line) = 0;
		/// Handle a runtime error.
virtual	void		OnRuntimeException(const char *error) = 0;

virtual	~IDebug() {}
};

protected:

		State			state;
		AutoPtr <IDebug> debug_interface;

public:

		BindingPluginManager binding_plugins;

		AutoPtr <Network::INetwork> peer_net;
		AutoPtr <HTTP::IHTTP> http;

/*!
	@name	Debugging interface.
	@{
*/
struct	CallStackEntry
{
		String		source, function;
		int			line;

		CallStackEntry(const char *s, const char *f, int l) : source(s), function(f), line(l) {}
};

		/// Get VM call stack.
virtual	void		GetCallStack(AutoList <CallStackEntry *> &callstack) { callstack.Clear(); }
/// @}

		/// Set VM state.
		void		SetState(State s) { state = s; }
		/// Get VM state.
		State		GetState() const { return state; }

		/// Get virtual machine name.
virtual	const char	*GetName() const = 0;

		/// Set VM event hook table.
virtual	void		SetDebugInterface(IDebug *, bool enable_debugging = false);
		/// Get the VM event hook table.
		IDebug		*GetEventHandler() const { return debug_interface; }

		/// Get a VM object.
virtual	Object		*GetObjectFromName(const char *name, const Object *context = 0) = 0;

		/// Compile a script.
virtual	bool		Compile(const char *source, uint size, const Object *context = 0, const char *sourcename = 0) = 0;
		/// Compile a script from file.
virtual	bool		CompileFile(const char *uri, const Object *context = 0);

		/// Create a script table.
virtual	Object		*CreateTable() = 0;
		/// Set a VM variable.
virtual	bool		Set(const char *name, const Variant &prop, const Object *context = 0) = 0;
		/// Get a VM variable.
virtual	bool		Get(const char *name, Variant &prop, const Object *context = 0) = 0;

		/// Create a script array.
virtual	Object		*CreateArray() = 0;
		/// Append a value to an array.
virtual	bool		Append(const Variant &, const Object *context = 0) = 0;

		/// Setup a function call in the VM.
virtual	bool		SetupFunctionCall(const char *func, const Object *function_object = 0, const Object *search_context = 0) = 0;
		/// Set function call context.
virtual	bool		SetFunctionCallContext(const Variant &) = 0;
		/// Push function call null argument.
virtual	bool		PushNullArgument() = 0;
		/// Push function call argument.
virtual	bool		PushArgument(const Variant &) = 0;
		/// Execute a function call in the VM, return value as a variant.
virtual	bool		DoFunctionCall(Variant *return_value = 0) = 0;

		/// Invalidate all references to a user object.
virtual	int			InvalidateNativeReference(void *) = 0;

		/// Is the VM open.
virtual	bool		IsOpen() const = 0;
		/// Open the script VM.
virtual	bool		Open() = 0;
		/// Crash the VM.
virtual	void		Kill(const char *reason);
		/// Close the script VM.
virtual	void		Close() = 0;

		IVM();
virtual	~IVM();
};

typedef	SharedPtr <IVM> sVM;

	} // Script
} // GS


#endif	// __SCRIPTVMINTERFACE__
