//===========================================================================//
// File:	l4app.hpp																			  //
// Project: MUNGA           Brick: L4Application								  	  //
// Contents: Interface specification for L4Application							  //
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 01/21/95  ECH  Initial coding.												  		  //
//---------------------------------------------------------------------------//
// Copyright (C) 1994, Virtual World Entertainment, Inc.                     //
//   All Rights reserved worldwide.                                          //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//

#pragma once

#include "..\munga\app.h"
#include "..\munga\APPMGR.h"

class DPLRenderer;
class L4AudioRenderer;
class L4GaugeRenderer;
class L4NetworkManager;
class LBE4ControlsManager;
class L4IcomManager;

//##########################################################################
//########################    L4Application    #############################
//##########################################################################

class L4Application:
	public Application
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction, Destruction, and Testing
//
public:
	L4Application(
		HINSTANCE hInstance,
		HWND hWnd,
		ResourceFile *resource_file,
		ApplicationID application_ID,
		ClassID class_ID=L4ApplicationClassID,
		SharedData &shared_data=DefaultData
	);
	~L4Application();

	Logical
		TestInstance() const;

	static Derivation *GetClassDerivations();
	static SharedData DefaultData;

	bool IsDead() {return mIsDead;}
	void SetIsDead(bool isDead) {mIsDead = isDead;}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Command line parsing
//
public:
	typedef Logical
		(*TokenParser)(int *argument, int argc, LPWSTR argv[]);
	static Logical
		ParseToken(
			int *argument,
			int argc,
			LPWSTR argv[]
		);
	static Logical
		ParseCommandLine(
			int argc,
			LPWSTR argv[],
			TokenParser parser = &L4Application::ParseToken
		);

	static int GetMissionReviewMode() { return missionReviewMode; }
	static HINSTANCE GetAppInstance() { return mhInstance; }
	static HWND GetMainWindow() { return ghWnd; }
	static unsigned int GetScreenWidth() { return mScreenWidth; }
	static unsigned int GetScreenHeight() { return mScreenHeight; }
	static bool GetFullscreen() { return mFullscreen; }
	static Logical GetSeeSolids() { return seeSolids; }
	static unsigned long GetNetworkCommonFlatAddress() { return networkCommonFlatAddress; }
	// The front end's multiplayer path turns network mode on at launch
	// time (the owner pod meshes like any other pod); command-line -net
	// keeps working exactly as before.
	static void SetNetworkCommonFlatAddress(unsigned long address) { networkCommonFlatAddress = address; }
	static CString GetEggNotationFileName() { return eggNotationFileName; }
	// the in-game front end builds an egg and injects it here
	static void SetEggNotationFileName(const char *name) { eggNotationFileName = name; }
	static CString GetSpoolFileName()		{ return spoolFileName; }
	static CString GetRIOPlaybackFileName() { return rioPlaybackFileName; }
	static CString GetRIORecordingFileName() { return rioRecordingFileName; }

protected:
	static HINSTANCE mhInstance;
	static unsigned int mScreenWidth;
	static unsigned int mScreenHeight;
	static bool mFullscreen;
	static Logical seeSolids;
	static CString eggNotationFileName;
	static CString spoolFileName;
	static unsigned long networkCommonFlatAddress;
	static int missionReviewMode;
	static CString rioPlaybackFileName;
	static CString rioRecordingFileName;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Execution control
//
public:
	void
		Initialize();
	void
		InitializeTillConsole();

	Entity*
		MakeAndLinkViewpointEntity(Entity__MakeMessage *message);

	Entity*
		MakeViewpointEntity(Entity__MakeMessage *message);

	void
		Terminate();

	void
		TeslaCoil(Logical lights_on);

	void
		PilotIllumination(Logical lights_on);		// includes 'Tesla coil'

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Module accesors
//
public:
	DPLRenderer*
		GetVideoRenderer();

	L4AudioRenderer*
		GetAudioRenderer();

	L4GaugeRenderer*
		GetGaugeRenderer();

	L4NetworkManager*
		GetNetworkManager()
			{return (L4NetworkManager*)Application::GetNetworkManager();}
	LBE4ControlsManager*
		GetControlsManager()
			{return (LBE4ControlsManager*)Application::GetControlsManager();}
	L4IcomManager*
		GetIntercomManager()
			{return (L4IcomManager*)Application::GetIntercomManager();}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Public data
//
public:
	char
		*divisionParameters;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Module Creation
//
protected:
	ModeManager*
		MakeModeManager();

	ControlsManager*
		MakeControlsManager();

	IcomManager*
		MakeIntercomManager();

	NetworkManager*
		MakeNetworkManager();

	VideoRenderer*
		MakeVideoRenderer();

	AudioRenderer*
		MakeAudioRenderer();

	GaugeRenderer*
		MakeGaugeRenderer(int *secondaryIndex, int *aux1Index, int *aux2Index);

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Message Support
//
public:
	enum
	{
		LightsOutMessageID = Application::NextMessageID,
		NextMessageID
	};

	static const HandlerEntry
		MessageHandlerEntries[];
	//static MessageHandlerSet MessageHandlers;
	static MessageHandlerSet& GetMessageHandlers();

	void
		LightsOutMessageHandler(Receiver::Message *message);
	void
		RunMissionMessageHandler(RunMissionMessage *message);
	void
		StopMissionMessageHandler(StopMissionMessage *message);
	void			 // HACK - the 'int' is actually 'ControlsKey'
		KeyCommandMessageHandler(ReceiverDataMessageOf<int> *message);

private:
	bool mIsDead;
};

extern L4Application * &l4_application;

//~~~~~~~~~~~~~~~~~~~~~ L4Application inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

inline DPLRenderer*
	L4Application::GetVideoRenderer()
		{
			Check(this);
			return (DPLRenderer*)videoRenderer;
		}

inline L4AudioRenderer*
	L4Application::GetAudioRenderer()
		{
			Check(this);
			return (L4AudioRenderer*)audioRenderer;
		}

inline L4GaugeRenderer*
	L4Application::GetGaugeRenderer()
		{
			Check(this);
			return (L4GaugeRenderer*)gaugeRenderer;
		}