#include "munga.h"
#pragma hdrstop

#include "cammppr.h"

//#############################################################################
// Shared Data Support
//
CameraControlsMapper::SharedData
	CameraControlsMapper::DefaultData(
		CameraControlsMapper::GetClassDerivations(),
		CameraControlsMapper::GetMessageHandlers(),
		CameraControlsMapper::GetAttributeIndex(),
		CameraControlsMapper::StateCount
	);

Derivation* CameraControlsMapper::GetClassDerivations()
{
	static Derivation classDerivations(Subsystem::GetClassDerivations(), "CameraControlsMapper");
	return &classDerivations;
}

//#############################################################################
// Messaging Support
//
const Receiver::HandlerEntry
	CameraControlsMapper::MessageHandlerEntries[]=
{
	MESSAGE_ENTRY(CameraControlsMapper, Keypress),
	MESSAGE_ENTRY(CameraControlsMapper, DirectorMode),
	MESSAGE_ENTRY(CameraControlsMapper, IncrementCamera),
	MESSAGE_ENTRY(CameraControlsMapper, DecrementCamera),
	MESSAGE_ENTRY(CameraControlsMapper, CreateCameraInstance),
	MESSAGE_ENTRY(CameraControlsMapper, DeleteCameraInstance),
	MESSAGE_ENTRY(CameraControlsMapper, OutputCameraInstances)
};

CameraControlsMapper::MessageHandlerSet& CameraControlsMapper::GetMessageHandlers()
{
	static CameraControlsMapper::MessageHandlerSet messageHandlers(ELEMENTS(CameraControlsMapper::MessageHandlerEntries), CameraControlsMapper::MessageHandlerEntries, Subsystem::GetMessageHandlers());
	return messageHandlers;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	CameraControlsMapper::KeypressMessageHandler(
		ReceiverDataMessageOf<ControlsKey> *message
	)
{
	Check(this);
	Check(message);

	switch (message->dataContents)
	{
		case 'd':
		case 'D':
		{
			ReceiverDataMessageOf<ControlsButton>
				button_message2(
					CameraControlsMapper::DirectorModeMessageID,
					sizeof(ReceiverDataMessageOf<ControlsButton>),
					1
				);
			Dispatch(&button_message2);
			break;
		}

		case 'o':
		case 'O':
		{
			ReceiverDataMessageOf<ControlsButton>
				button_message2(
					CameraControlsMapper::OutputCameraInstancesMessageID,
					sizeof(ReceiverDataMessageOf<ControlsButton>),
					1
				);
			Dispatch(&button_message2);
			break;
		}
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	CameraControlsMapper::DirectorModeMessageHandler(
		ReceiverDataMessageOf<ControlsButton> *message
	)
{
	if (message->dataContents > 0)
	{
		CameraShip *camera = GetEntity();
		Check(camera);
		if(camera->GetSimulationState() != CameraShip::ConfigureCamerasState)
		{
			camera->SetPerformance(&CameraShip::DriveCamera);
			camera->SetSimulationState(CameraShip::ConfigureCamerasState);
			CameraInstance *cam = camera->GetCurrentCamera();
			Check(cam);
			//DEBUG_STREAM << cam->GetCameraName() << std::endl << std::flush;
		}
		else
		{
			camera->SetPerformance(&CameraShip::FollowGoal);
			camera->SetSimulationState(CameraShip::DefaultState);
         camera->lastSwitch = Now();
		}
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	CameraControlsMapper::IncrementCameraMessageHandler(
		ReceiverDataMessageOf<ControlsButton> *message
	)
{
	if(message->dataContents > 0)
	{
		CameraShip *camera = GetEntity();
		Check(camera);
		camera->IncrementCameraInstance();
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	CameraControlsMapper::DecrementCameraMessageHandler(
		ReceiverDataMessageOf<ControlsButton> *message
	)
{
	if (message->dataContents > 0)
	{
		CameraShip *camera = GetEntity();
		Check(camera);
		camera->DecrementCameraInstance();
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	CameraControlsMapper::CreateCameraInstanceMessageHandler(
		ReceiverDataMessageOf<ControlsButton> *message
	)
{
	if (message->dataContents > 0)
	{
		CameraShip *camera = GetEntity();
		Check(camera);
		camera->CreateCameraInstance();
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	CameraControlsMapper::DeleteCameraInstanceMessageHandler(
		ReceiverDataMessageOf<ControlsButton> *message
	)
{
	if (message->dataContents > 0)
	{
		CameraShip *camera = GetEntity();
		Check(camera);
		camera->DeleteCameraInstance();
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	CameraControlsMapper::OutputCameraInstancesMessageHandler(
		ReceiverDataMessageOf<ControlsButton> *message
	)
{
	if (message->dataContents > 0)
	{
		CameraShip *camera = GetEntity();
		Check(camera);
		camera->OutputCameraList();
	}
}

//#############################################################################
// Attribute Support
//
const CameraControlsMapper::IndexEntry
	CameraControlsMapper::AttributePointers[]=
{
	ATTRIBUTE_ENTRY(CameraControlsMapper, StickPosition, stickPosition),
	ATTRIBUTE_ENTRY(CameraControlsMapper, ThrottlePosition, throttlePosition),
	ATTRIBUTE_ENTRY(CameraControlsMapper, PedalsPosition, pedalsPosition),
	ATTRIBUTE_ENTRY(CameraControlsMapper, ReverseThrust, reverseThrust),
	ATTRIBUTE_ENTRY(CameraControlsMapper, DriveCamera, driveCamera),
	ATTRIBUTE_ENTRY(CameraControlsMapper, SlideOrClamp, slideOrClamp)
};

CameraControlsMapper::AttributeIndexSet& CameraControlsMapper::GetAttributeIndex()
{
	static CameraControlsMapper::AttributeIndexSet attributeIndex(ELEMENTS(CameraControlsMapper::AttributePointers),
		CameraControlsMapper::AttributePointers,
		Subsystem::GetAttributeIndex()
	);
	return attributeIndex;
}

//#############################################################################
// Construction and Destruction
//

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraControlsMapper::CameraControlsMapper(
	CameraShip *owner,
	int subsystem_ID,
	SubsystemResource *subsystem_resource,
	SharedData &shared_data
):
	Subsystem(owner, subsystem_ID, subsystem_resource, shared_data)
{
	stickPosition.x = 0.0f;
	stickPosition.y = 0.0f;
	throttlePosition = 0.0f;
	pedalsPosition = 0.0f;
	driveCamera = 0;
	slideOrClamp = 0;
   reverseThrust = 0;
	Check_Fpu();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraControlsMapper::~CameraControlsMapper()
{
}

Logical
	CameraControlsMapper::TestInstance() const
{
	return IsDerivedFrom(*GetClassDerivations());
}
