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


		#include "script/script_vm_debug_profile_base.h"

		using namespace GS;
		using namespace GS::Script;


//------------------------------------------------------------------------------
String		IDebuggerProfiler::ConvertCallStackToMetaString(const AutoList <IVM::CallStackEntry *> &callstack, int current_stack_frame)
{
	String data = "<SetCallStack=\n";
	int level = 0;
	ListForeachPtr(IVM::CallStackEntry *, frame, callstack)
	{
		data += "<Frame=";
		data += String::Format("<Source=\"%s\"><Function=\"%s\"><Line=%d>", frame->source.c_str(), frame->function.c_str(), frame->line);
		if	(level == current_stack_frame)
			data += "<IsCurrent>";
		data += ">\n";
		++level;
	}
	data += ">";
	return data;
}
String		IDebuggerProfiler::GetCallstack()
{
	AutoList <IVM::CallStackEntry *> callstack;
	vm->GetCallStack(callstack);
	return ConvertCallStackToMetaString(callstack, debugger->GetDebugStackFrame());
}
String		IDebuggerProfiler::GetDebugStackFrameLocals()
{
	debugger->RefreshStackFrameLocalsCache();
	return debugger->GetStackFrameLocals();
}
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
void		IDebuggerProfiler::Kill()
{
/*
	// Kill the VM in order to escape infinite loops.
	SquirrelVM &squirrel_vm = (SquirrelVM &)vm;
	if	(squirrel_vm.VM())
		sq_setalive(squirrel_vm.VM(), false);
*/

	// FIXME
}
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
void		IDebuggerProfiler::OnStep(char type, const char *source, int line, const char *func)
{
	// FIXME the stack querying system should be abstracted and go through VM interface calls.
/*
	if	(profiler.IsValid())
	{
		HSQUIRRELVM	hvm = ((SquirrelVM &)vm).VM();

		// Update profiler if currently profiling.
		if	(profiler.IsProfiling())
		{
			Profiler::FunctionProfile *profile = 0;

			SQStackInfos si;
			int depth = 0;
			while (SQ_SUCCEEDED(sq_stackinfos(hvm, depth++, &si)))
				;
			while (depth > 0)
				if	(SQ_SUCCEEDED(sq_stackinfos(hvm, --depth, &si)))
					profile = profiler.GetFunctionProfile(si.source, si.funcname, (int)si.line, profile);

			if	(profile)
				profiler.Update((int)type, profile);
		}
	}
*/

	if	(debugger.IsValid())
	{
		// Check for breakpoint.
		debugger->CheckSuspendOnBreakpoint(source, line);

		// Refresh the debugger UI.
		debugger->SetDebugStackFrame(debugger->GetStackFrameIndex());

		if	(debugger->IsStepping())
			debugger->CheckSuspendOnStep();

		if	(debugger->IsSuspended())	// might now be suspended after the previous step check
			OnSuspendExecution(source, line);

		// Suspend execution.
		while (debugger->IsSuspended() && (vm->GetState() != IVM::StateDead))
			if	(!OnUpdateSuspendedExecution())	// wait for handler resume signal
				debugger->Resume();
	}
}
//------------------------------------------------------------------------------

IDebuggerProfiler::IDebuggerProfiler(IVM *script_vm, IDebugger *idbg) : vm(script_vm), debugger(idbg) {}
