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


		#include "viewer_base/viewer_base_debugger.h"
		#include "viewer_base/viewer_base.h"
		#include "io_net/io_net_client.h"
		#include "async/task_loop.h"
		#include "filesystem/io_buffer.h"
		#include "filesystem/filesystem.h"

		using namespace GS;
		using namespace GS::Script;


//------------------------------------------------------------------------------
void		ViewerBaseDebugger::SetViewerStatus(const char *status)
{	__LOG__ << "Viewer: " << status << "\n";	}
IO::Base	*ViewerBaseDebugger::WrapRemoteFileSystem(IO::Base *remote_fs)
{	return new IO::Buffer(remote_fs, 65536, 65536);		}
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
void		ViewerBaseDebugger::OnControllerPacketReceived(const Array <char> &data)
{
	using namespace NML;

	Tag tag;
	Parser::ParseTag(tag, data.Start(), data.End());

			if	(tag.name == "ShowPerformanceProfiler")
			viewer.enable_profiler = tag.GetBool();
	else	if	(tag.name == "ShowMemoryProfiler")
			viewer.memory_profiler = tag.GetBool();
	else	if	(tag.name == "DebugPhysics")
	{
		if	(viewer.project.IsValid())
			viewer.project->flags.Raise(GS::Core::Project::ProjectFlagDebugPhysics, tag.GetBool());
		if	(viewer.scene_3d.IsValid())
			viewer.scene_3d->flags.Raise(GS::S3D::Scene::FlagDebugPhysics, tag.GetBool());
	}

	// Remote session setup.
	else	if	(tag.name == "MountRemoteFileSystem")
	{
		SetViewerStatus("Connecting to file server");

		String address = GetPeerAddress();

		int port = -1;
		if	(Tag *port_tag = tag.GetTypedTag("Port", GS::Variant::VariantInteger))
			port = port_tag->GetInteger();

		__LOG_H__ << "Mounting remote file system from " << address << " on port " << port << ".\n";

		if	(!address.IsEmpty() && (port != -1))
		{
			SharedPtr <IO::Net> net(new IO::Net);

			bool connection_status = false;

			if	(net->Connect(address, port))
			{
				// Wait for connection...
				__LOG_H__ << "Waiting for remote file system connection...\n";

				StartTaskLoop(net->IsConnected() == false, 10000) // 10s timeout
					Platform::Get().Sleep(1);
				EndTaskLoop

				if	((connection_status = net->IsConnected()) == true)
				{
					// Mount net FS through an IO cache layer.
					viewer.remote_fs = WrapRemoteFileSystem(net);
					Platform::Get().io->Mount(viewer.remote_fs);

					// Remote FS ready.
					BroadcastNetworkCommand("<RemoteFileSystemOk>");
				}
			}

			if	(connection_status == false)
				SetViewerStatus("File server connection failed");
		}
	}
	else	if	(tag.name == "SetSessionInput")
	{
		SetViewerStatus("Loading session");

		viewer.remote_project.Clear();
		if	(Tag *t = tag.GetTag("Environment"))
			viewer.remote_project.AddRoot(t->Clone());

		viewer.remote_scene.Clear();
		if	(Tag *t = tag.GetTag("Scene"))
			viewer.remote_scene.AddRoot(t->Clone());
		else if (Tag *t = tag.GetTag("Scene2D"))
			viewer.remote_scene.AddRoot(t->Clone());

		BroadcastNetworkCommand("<SetSessionInputOK>");
	}
	else	if	(tag.name == "StartSession")
	{
		SetViewerStatus("Session Running");
		viewer.state = ViewerBase::SessionSetup;	// setup session before starting it
	}
	else
		NetworkDebugger::OnControllerPacketReceived(data);
}
//------------------------------------------------------------------------------

ViewerBaseDebugger::ViewerBaseDebugger(ViewerBase &v, IDebugger *idbg, const char *address, int port) : NetworkDebugger(v.script_vm, idbg, address, port), viewer(v) {}
