#include "rpl4.h"
#pragma hdrstop

#include "rpl4app.h"
#include "rpl4vid.h"
#include "rpl4arnd.h"
#include "rpl4grnd.h"
#include "rpl4mssn.h"
#include "..\munga_l4\l4gauge.h"
#include "..\rp\rpreg.h"
#include "..\munga_l4\l4ctrl.h"
#include "..\munga_l4\l4mppr.h"
#include "..\munga\appmgr.h"
#include "rpl4mode.h"
#include "..\rp\vtv.h"
#include "rpl4mppr.h"
#include "..\rp\rpplayer.h"

//
//#############################################################################
// RPL4Application
//#############################################################################
//
RPL4Application::RPL4Application(
	HINSTANCE hInstance,
	HWND hWnd,
	ResourceFile *resource_file,
	ClassID class_ID,
	SharedData &shared_data
):
	L4Application(hInstance, hWnd, resource_file, RPL4, class_ID, shared_data)
{
	Check_Fpu();
}

//
//#############################################################################
// ~RPL4Application
//#############################################################################
//
RPL4Application::~RPL4Application()
{
	Check_Fpu();
}

//
//#############################################################################
// MakeRegistry
//#############################################################################
//
Registry*
	RPL4Application::MakeRegistry()
{
	Check_Fpu();
	return new RPRegistry(GetResourceFile());
}

//
//#############################################################################
// MakeVideoRenderer
//#############################################################################
//
VideoRenderer*
	RPL4Application::MakeVideoRenderer()
{
	if (divisionParameters)
	{
		return
			new RPL4VideoRenderer(
				ghWnd,
				L4Application::mScreenWidth,
				L4Application::mScreenHeight,
				L4Application::mFullscreen,
				VisualInterestType,
				DefaultInterestDepth
			);
	}
	return NULL;
}

//
//#############################################################################
// MakeAudioRenderer
//#############################################################################
//
AudioRenderer*
	RPL4Application::MakeAudioRenderer()
{
	Check_Fpu();
//	char *blaster1, *blaster2;

//	blaster1 = getenv(FRONT_CARD_ENV_VAR);
//	blaster2 = getenv(REAR_CARD_ENV_VAR);

	//if (blaster1 != NULL && blaster2 != NULL)
	//{
		return new RPL4AudioRenderer(
			1000.0f,
			GetMissionReviewMode()
		);
	//}
//	return NULL;
}

//#############################################################################
// MakeModeManager
//#############################################################################
ModeManager*
	RPL4Application::MakeModeManager()
{
	RPL4ModeManager
		*manager = new RPL4ModeManager(RPL4ModeManager::ModeInitial);
	Check(manager);
	return manager;
}

//
//#############################################################################
// MakeGaugeRenderer
//#############################################################################
//
GaugeRenderer*
	RPL4Application::MakeGaugeRenderer(int *secondaryIndex, int *aux1Index, int *aux2Index)
{
	char *mode_string = getenv("L4GAUGE");
	if (mode_string != NULL && (secondaryIndex != NULL || aux1Index != NULL || aux2Index != NULL))
	{
      return new RPL4GaugeRenderer(!L4Application::mFullscreen, secondaryIndex, aux1Index, aux2Index);
	}
	return NULL;
}

//
//#############################################################################
// MakeMission
//#############################################################################
//
Mission*
	RPL4Application::MakeMission(
		NotationFile *notation_file,
		ResourceFile *resources
	)
{
	Check(this);
	Check(notation_file);
	Check(resources);

	Check_Fpu();
	return new RPL4Mission(notation_file, resources);
}

//
//#############################################################################
// MakeViewpointEntity
//#############################################################################
//
Entity*
	RPL4Application::MakeViewpointEntity(Entity::MakeMessage *message)
{
	Check(this);

//	Entity
//		*viewing_entity = L4Application::MakeViewpointEntity(message);
//
//	if(viewing_entity)
//	{
//		Check_Fpu();
//		return viewing_entity;
//	}

	LBE4ControlsManager* controls =
		(LBE4ControlsManager *)GetControlsManager();
	Check(controls);

	Entity
		*viewing_entity = NULL;
	char
		*primary_mapping_name = NULL;

	switch(message->classToCreate)
	{
	case CameraShipClassID:
		//=======================================================================
		// Create Camera ship
		//=======================================================================
		{
			CameraShip
				*viewing_camera =
					CameraShip::Make((CameraShip::MakeMessage*)message);
			Check(viewing_camera);

			viewing_entity = viewing_camera;
			//--------------------------------------------------
			// Create controls mapping object
			//--------------------------------------------------
			CameraControlsMapper::SubsystemResource
				control_subsystem_resource;

			Str_Copy(
				control_subsystem_resource.subsystemName,
				"ControlsMapper",
				sizeof(control_subsystem_resource.subsystemName)
			);
			control_subsystem_resource.classID = TrivialSubsystemClassID;
			control_subsystem_resource.subsystemModelSize =
				sizeof(control_subsystem_resource);

			CameraControlsMapper
				*camera_mapper;

			switch (controls->primaryControlType)
			{
			case LBE4ControlsManager::PrimaryThrustMaster:
				Tell("RPL4Application, CameraShip using ThrustMaster\n");
				camera_mapper = new CameraThrustmasterMapper(
					viewing_camera,
					CameraShip::ControlsMapperSubsystem,
					&control_subsystem_resource
				);
				primary_mapping_name = "Thrustmaster";
				break;

			case LBE4ControlsManager::PrimaryRIO:
				Tell("RPL4Application, CameraShip using RIO\n");
				camera_mapper = new CameraRIOMapper(
					viewing_camera,
					CameraShip::ControlsMapperSubsystem,
					&control_subsystem_resource
				);
				primary_mapping_name = "L4";
				break;

			default:
				Tell("RPL4Application, CameraShip using default mapper\n");
				camera_mapper = new CameraL4Mapper(
					viewing_camera,
					CameraShip::ControlsMapperSubsystem,
					&control_subsystem_resource
				);
				// primary mapping name is NULL
				break;
			}

			//-------------------------------------------
			// Set mapping subsystem for this entity
			//-------------------------------------------
			Register_Object(camera_mapper);
			viewing_camera->SetMappingSubsystem(camera_mapper);
		}
		break;

	case VTVClassID:
		//=======================================================================
		// Create VTV
		//=======================================================================
		{
			VTV
				*viewing_VTV = VTV::Make((VTV::MakeMessage*)message);
			Check(viewing_VTV);

			viewing_entity = viewing_VTV;
			//--------------------------------------------------
			// Set control deadbanding
			//--------------------------------------------------
			controls->SetJoystickDeadBand(.1);
			controls->SetThrottleDeadBand(.1);
			controls->SetPedalsDeadBand(.1);
			//--------------------------------------------------
			// Create controls mapping object
			//--------------------------------------------------
			VTVControlsMapper::SubsystemResource
				control_subsystem_resource;
			Str_Copy(
				control_subsystem_resource.subsystemName,
				"ControlsMapper",
				sizeof(control_subsystem_resource.subsystemName)
			);
			control_subsystem_resource.classID = TrivialSubsystemClassID;
			control_subsystem_resource.subsystemModelSize =
				sizeof(control_subsystem_resource);
			control_subsystem_resource.segmentIndex = -1;
			control_subsystem_resource.subsystemFlags = 0;

			VTVControlsMapper
				*vtv_mapper;

			switch (controls->primaryControlType)
			{
			case LBE4ControlsManager::PrimaryThrustMaster:
				Tell("RPL4Application, VTV using ThrustMaster\n");
				vtv_mapper = new VTVThrustmasterMapper(
					viewing_VTV,
					VTV::ControlsMapperSubsystem,
					&control_subsystem_resource
				);
				primary_mapping_name = "Thrustmaster";
				break;

			case LBE4ControlsManager::PrimaryRIO:
				Tell("RPL4Application, VTV using RIO\n");
				vtv_mapper = new VTVRIOMapper(
					viewing_VTV,
					VTV::ControlsMapperSubsystem,
					&control_subsystem_resource
				);
				primary_mapping_name = "L4";
				break;

			default:
				DEBUG_STREAM << "*****VTV has no controls mapping!*****" << std::flush;
				Fail("RPL4Application::MakeViewpointEntity");
				vtv_mapper = NULL;
				// primary mapping name is NULL
				break;
			}

			//-------------------------------------------
			// Set mapping subsystem for this entity
			//-------------------------------------------
			Register_Object(vtv_mapper);
			viewing_VTV->SetMappingSubsystem(vtv_mapper);
			//-------------------------------------------
			// Enable collision detection for this entity
			//-------------------------------------------
			viewing_VTV->StartCollisionAssistant();
		}
		break;
	}
	Check(viewing_entity);

	//------------------------------------------------------------------------
	// Load up the control mapping stream for the entity
	//------------------------------------------------------------------------
	if (primary_mapping_name != NULL)
	{
		ResourceDescription
			*resource_description =
				application->GetResourceFile()->SearchList(
					viewing_entity->GetResourceID(),
					ResourceDescription::ControlMappingsListResourceType
				);

		if (resource_description != NULL)
		{
			Check(resource_description);

			Check(GetResourceFile());
			resource_description =
				GetResourceFile()->SearchList(
					resource_description->resourceID,
					primary_mapping_name
				);

			if (resource_description != NULL)
			{
				Check(resource_description);

				resource_description->Lock();
				controls->CreateStreamedMappings(
					viewing_entity,
					(int*)resource_description->resourceAddress
				);
				resource_description->Unlock();
			}
		}
	}

	//------------------------------------------------------------------------
	// Create gauges for this entity
	//------------------------------------------------------------------------
	RPL4GaugeRenderer
		*gauge_renderer = (RPL4GaugeRenderer *) GetGaugeRenderer();

	if (gauge_renderer != NULL)
	{
		Check(gauge_renderer);
		gauge_renderer->ConfigureForModel("Init", viewing_entity);
	}

	Check_Fpu();
	return viewing_entity;
}
