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


#ifndef	__VIEWERBASE__
#define	__VIEWERBASE__


		#include "viewer_base/viewer_base_vmhook.h"
		#include "gpu/gpu_triangle_batch.h"
		#include "project/project.h"
		#include "scene3d/scene.h"
		#include "ui/ui.h"
		#include "core/mixer.h"
		#include "core/renderer.h"
		#include "core/resource_factories.h"
		#include "core/graphic_resource_factory.h"
		#include "core/render_resource_factory.h"
		#include "core/mixer_resource_factory.h"
		#include "debug_enet/network_debugger.h"
		#include "io_net/io_net_client.h"
		#include "timing/loop_benchmark.h"
		#include "container/nstack.h"


namespace GS {

/*
	@short	Engine viewer base class.

	Derive from this class and implement the pure virtual functions to create
	a platform specific viewer.

	@author	Emmanuel Julien (ejulien@gsworks.fr)
*/
class	ViewerBase
{
		String		GetBaseCommandLineParm() const;

public:

enum	SessionType
{
	SessionScene		=	0,
	SessionProject
};

enum	SessionSource
{
	SessionSourceFilesystem		=	0,
	SessionSourceArchive,
	SessionSourceArchiveBootstrap
};

enum	State
{
	ViewerSetup			=	0,
	ViewerClose,

	WaitRemoteSetup,
	WaitRemoteController,

	SessionSetup,
	SessionRunning,
	SessionClose,
};

		State			state;

protected:

		bool			paused;
		bool			missing_resource;

		LoopBenchmark	fps;

		AutoPtr <GPU::TriangleBatch> gpu_batch;

virtual	bool			OpenVideo() = 0;
virtual	bool			OpenAudio() = 0;

		bool			LoadSessionData();

		List <Variant *> define_list;
		StringList		include_list;

		/// Platform specific update.
virtual	bool			PlatformUpdate() = 0;

		/// Called when a command line parameter is unknown to the base command line parser.
virtual	bool			OnUnknownCommandLineParam(Stack <String> &_arg, int &n) { return false; }
		/// Print additional usage.
virtual	void			PrintAdditionalUsage() {}

virtual	bool			OpenScriptVM();
		void			SetVMGlobals();

		bool			OpenSession();
virtual	void			ExecuteSession();
		bool			CheckRuntimeError();
		void			CloseSession();

		void			ExecuteMonitor();

virtual	Script::NetworkDebugger *CreateVMDebugInterface();

public:

		void			PrintHeader();
		void			PrintUsage();

enum	MessageType
{
	MessageNormal		=	0,
	MessageWarning,
	MessageError
};

		/// Platform specific display message to the user.
virtual	void			DisplayUserMessage(MessageType, const char *) = 0;

		/// Instantiate the renderer object.
virtual	bool			CreateRenderer() = 0;
		/// Instantiate the mixer object.
virtual	bool			CreateMixer() = 0;

		bool			SetupSessionSource();

		NML::File		config_file;

		SessionSource	session_source;
		SessionType		session_type;

		String			s_render, s_mixer;
		String			mixer_output;
		String			session_source_path;
		String			input_path;
		String			config_path;
		String			raytrace_path;

		String			bootstrap_script;

		int				raytrace_width,
						raytrace_height,
						raytrace_aa;

		int				time_start,
						time_live;

		int				frame_count;

		bool			ignore_esc,
						ignore_bootstrap,
						ignore_missing_resource;

		bool			enable_profiler,
						memory_profiler,
						enable_pause,
						display_fps;

		bool			active_debug;
		//---------------------------------------------------------------------
		bool			remote;
		int				remote_port;

		SharedPtr <IO::Base> remote_fs;

		NML::File		remote_project,
						remote_scene;
		//---------------------------------------------------------------------

		bool			tool_mode;

		bool			safe_mode;
		bool			fullscreen;
		int				width, height;
		float			aspect_ratio;

		Script::sVM		script_vm;
		Script::NetworkDebugger *script_debugger;

		Core::sResourceFactories factories;

		AutoPtr <Render::Renderer> renderer;
		AutoPtr <Audio::IMixer> mixer;

		AutoPtr <Core::Project> project;
		AutoPtr <S2D::Scene> scene_2d;
		AutoPtr <S3D::Scene> scene_3d;

		Render::RasterFont *profiler_font[2], *fps_font;

/*!
	@name	Viewer API
	@{
*/
		/// Application has been sent to background.
		void			Suspend();
		/// Application returned to foreground.
		void			Resume();

		bool			ParseCommandLine(Stack <String> &_arg);
		bool			LoadViewerConfig(const char *path);

		bool			LocateAndParseBootstrap(Stack <String> &_arg);
		void			SetupVersion(const char *);

virtual	bool			OpenViewer();
virtual	State			Execute();
virtual	void			CloseViewer();
/// @}

		ViewerBase();
virtual	~ViewerBase()	{ CloseViewer(); }
};

} // GS


#endif	// __VIEWERBASE__
