//===========================================================================//
// File:	Application.hpp
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 08/25/97  ECH  Infrastructure changes.                                    //
//---------------------------------------------------------------------------//
// Copyright (C) 1995-97, Virtual World Entertainment, Inc.                  //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//

#pragma once
 
#include "Adept.hpp"
#include "Network.hpp"
#include "Event.hpp"
#include "State.hpp"
#include "ReplicatorID.hpp"
#include "Entity.hpp"
#include "Player.hpp"
#include "GlobalPointerManager.hpp"

#include <Stuff\Point3D.hpp>

namespace NetMissionParameters
{
	class AdeptNetMissionParameters:
		public Stuff::Plug
	{
	public:
		int m_runDedicated;
		int m_closedGame;
		int m_playerLimit;
		

		int m_visibility;

		
		AdeptNetMissionParameters();

		virtual void ResetParameters(void);
		virtual void SaveParameters(Stuff::DynamicMemoryStream *stream);
		virtual void LoadParameters(Stuff::MemoryStream *stream);

		virtual void SaveParameters(Stuff::NotationFile *notefile);
		virtual void LoadParameters(Stuff::NotationFile *notefile);
		virtual void LoadOverideParameters(Stuff::NotationFile *notefile);

		virtual void SaveServerParameters(Stuff::NotationFile *notefile);

	};
}

#ifdef LAB_ONLY
namespace MWGameInfo
{
	const int Packet_History_Count = 200;
	
	const int MAX_GAME_INFO_STR_LEN = 255;

	extern int g_currentApplicationPhase;
	extern int g_currentApplicationState;

	extern Stuff::Point3D g_LastCameraPos;
	extern Stuff::Point3D g_LastLocalPlayerPos;

	enum {
		NoPhase = 0,
		PreCollisionPhase,
		CollisionPhase,
		SyncPhase,
		PostCollisionPhase,
		NetworkPhase,
		UpdateRendererPhase,
		RenderPhase,
		GameOSPhase,
		PhaseCount
	};

	enum {
		NoState = 0,
		WaitingForGameState,
		LoadingGameState,
		PreRenderState,
		RunningGameState,
		StoppingGameState,
		RecycleGameState,
		StateCount
	};

	
	extern char g_LastFileOpenRequest[MAX_GAME_INFO_STR_LEN*2];

	
	extern char *g_applicationPhases[PhaseCount];
	extern char *g_applicationStates[StateCount];



	extern int g_lastPacketAddress[Packet_History_Count];
	extern int g_lastPacketType[Packet_History_Count];
	extern int g_lastPacketSize[Packet_History_Count];
	extern bool g_lastPacketInbound[Packet_History_Count];
	extern double g_lastPacketTime[Packet_History_Count];
	extern int nextPacketHistoryIndex;
	

}
#endif


namespace Adept {

	extern double g_lastPacketFromPlayer[Adept::Maximum_Connection_Numbers];
	extern double g_lastPacketToPlayer[Adept::Maximum_Connection_Numbers];




	//~~~~~~~~~~~~~~~~~~~~~~~~~~ Forward declarations ~~~~~~~~~~~~~~~~~~~~~~~~~~

	class Application;
	class HermitEntry;
	class Mission;
	class ResourceManager;
	class Map;
	class RendererManager;
	class ControlsManager;
	class Entity;
	class Connection;
	class EntityManager;
	class ControlsManager;
	class RendererManager;
	class BackgroundTasks;
	class NetworkManager;


	const int Maximum_Players=static_cast<int>(255);
	const int MaxChatSize=static_cast<int>(222);

   //##########################################################################
	//###################    ApplicationStateEngine    #########################
	//##########################################################################

	class ApplicationStateEngine:
		public StateEngine
	{
	public:
		static void
			InitializeClass();
		static void
			TerminateClass();

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Construction and Destruction
	//
	public:
		ApplicationStateEngine(
			ClassData *class_data,
			int state_number,
			Application *the_application
		);
		~ApplicationStateEngine();

		void
			TestInstance();

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Class Data Support
	//
	public:
		static ClassData 
			*DefaultData;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// State stuff
	//
	
	public:
		enum {
			InitializingState = StateEngine::StateCount,
			
			WaitingForGameState,
			LoadingGameState,
			PreRenderState,
			RunningGameState,
			StoppingGameState,
			RecycleGameState,
			StateCount
		};

		int
			RequestState(
				int new_state,
				void* data = NULL
			);

	protected:
		static const StateEntry
			StateEntries[];

		Application
			*owningApplication;
	};



	//##########################################################################
	//#########################    Application    ##############################
	//##########################################################################

	typedef InBox__Message			Application__Message;
	typedef Application__Message	Application__RunGameMessage;
	typedef Application__Message	Application__PauseGameMessage;


	class Application:
		public InBox
	{
		friend class ApplicationStateEngine;

	public:
		static void
			InitializeClass();
		static void
			TerminateClass();

		typedef Application__Message						Message;
		
		typedef Application__PauseGameMessage				PauseGameMessage;
		

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Command line parsing
	//
	public:
		static Application*
			GetInstance() 
		{
			return reinterpret_cast<Application *>( GlobalPointers::GetGlobalPointer(ApplicationGlobalPointerIndex));
		};

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Construction, Destruction, and Testing
	//
	public:
		Application(ClassData *class_data);
		~Application();

		void
			TestInstance();

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Execution control
	//
	public:
		static void __stdcall GetFileForGOS(
			const char* filename,
			BYTE** memory,
			DWORD* size
		);

		static bool __stdcall FindFileForGOS(const char* filename);

		virtual void
			Initialize();

		virtual void
			LoadBackgroundTasks();

		static void _stdcall
			DoGameLogic();

		static void _stdcall
			UpdateDisplay();

		virtual void
			StopGame();

		virtual void
			Terminate();

		void
			PauseGame()
				{Check_Object(this); gamePause = true;}
		void
			UnpauseGame()
				{Check_Object(this); gamePause = false;}
		bool
			IsPaused()
				{Check_Object(this); return gamePause;}

		virtual void
			RecycleNetworking();

		virtual void
			StopNetworking();

		virtual void
			SessionLost(){STOP(("VIRTUAL BASE NOT IMPLEMENTED"));};

		virtual void
			QueStopGame(bool no_recyle = false)
				{Check_Object(this); quedStop = true;}

		bool
			QuedForStop()
				{Check_Object(this); return quedStop;}


		virtual void
			SendChat(BYTE from, BYTE type, BYTE player_sent_to, char *message){};


		virtual char *
			GetLocString(int index)=0;

	protected:
		bool
			gamePause;
		bool
			quedStop;
	public:
		bool
			serverFlag;
		bool
			networkingFlag;
		static int
			s_ScreenWidth;
		static int
			s_ScreenHeight;
		static bool
			s_DiskFirst;
	
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	public:
		int
			currentGameNumber;

		Stuff::LinearMatrix4D
			preRenderDropLocation;
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Adept Message Support
	//
	public:
		enum {
			LoadQuickGameMessageID = InBox::NextMessageID,
			SaveQuickGameMessageID,
			PauseGameMessageID,
			NextMessageID
		};

		void
			LoadQuickGameMessageHandler(const ReceiverDataMessageOf<int> *message);
		void
			SaveQuickGameMessageHandler(const ReceiverDataMessageOf<int> *message);
		void
			PauseGameMessageHandler(const ReceiverDataMessageOf<int> *message);
		
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Network Support
	//

		virtual void 
			ConnectClient(int connection,Connection *con){STOP(("NOT IMPLEMENTED"));};

		virtual void 
			DisconnectClient(int connection,Connection *con){STOP(("NOT IMPLEMENTED"));};

		virtual void
			ReceiveDirectMessage(int connection, int message_type, Stuff::MemoryStream *message){STOP(("NOT IMPLEMENTED"));};
		
		virtual void
			ConnectServer(){STOP(("NOT IMPLEMENTED"));};

		virtual bool
			CheckValidDrop(Point3D position){return true;};

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	


	protected:
		static const MessageEntry
			MessageEntries[];

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Application State
	//
	public:
		int
			GetApplicationState()
				{Check_Object(applicationState);return applicationState->GetState();}

	protected:
		ApplicationStateEngine
			*applicationState;

		virtual void
			EnterRunningGameState(void *data);
		virtual void
			EnterStoppingGameState(void* data);
		virtual void
			EnterLoadingGameState(void* data);
		virtual void
			EnterRecyclingGameState(void* data);
		virtual void
			EnterPreRenderState(void* data);


	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Accessors
	//
	public:

		NetMissionParameters::AdeptNetMissionParameters *
			m_localMissionParameters;
		NetMissionParameters::AdeptNetMissionParameters *
			m_serverMissionParameters;

		static int
			TraceLogSize;
		static bool
			BuildOK,
			TestClasses,
			RunOK;
		

		bool
			InPreCollisionPhase()
				{Check_Object(this); return preCollisionPhase;}

	protected:
		bool
			preCollisionPhase;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Editor Support
	//
	public:
		enum {
			NormalGameMode = 0, 
			EditorMode
		};

		int 
			applicationMode;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Class Data Support
	//
	public:
		static ClassData 
			*DefaultData;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Protected data
	//
	protected:
		BackgroundTasks
			*backgroundTasks;
#ifdef LAB_ONLY
	public:
		static bool 
				ReportNotResourced;
#endif
	public: // jcem
		virtual int CheckCampaign(int nType) const { return 0; }
		int IsCampCOOP() const { return CheckCampaign(-1); }
	};


}
