#pragma once

#include "..\rp\vtvmppr.h"

class L4Lamp;

//##########################################################################
//####################    ThrustmasterMapper    ############################
//##########################################################################

class L4VTVControlsMapper:
	public VTVControlsMapper
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Shared Data Support
//
public:
	static Derivation *GetClassDerivations();
	static SharedData DefaultData;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Messaging Support
//
public:
	enum {
		KeypressMessageID = VTVControlsMapper::NextMessageID,
		NextMessageID
	};

	void
		KeypressMessageHandler(ReceiverDataMessageOf<ControlsKey> *message);

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

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Model Support
//
public:
	typedef void
		(L4VTVControlsMapper::*Performance)(Scalar time_slice);

	void
		SetPerformance(Performance performance)
			{
				Check(this);
				activePerformance = (Simulation::Performance)performance;
			}

	void
		CreateTemporaryEventMappings(
			Receiver *receiver,
			Receiver::MessageID config_message_id
		),
		RemoveTemporaryEventMappings(),
		AddOrErase(
			unsigned int button_ID,
			Receiver *target,
			Receiver::MessageID message_ID
		),
		AddOrErase(
			unsigned int button_ID,
			ControlsButton *destination
		);

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction and Destruction Support
//
public:
	L4VTVControlsMapper(
		VTV *player_vehicle,
		int subsystem_ID,
		SubsystemResource *subsystem_resource,
		SharedData &shared_data = DefaultData
	);
	~L4VTVControlsMapper();

	Logical
		TestInstance() const;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Controls mode switching
//
void
	SetControlsMode(int new_mode),
	SetConfigurationMode(Logical new_state);

void
	NotifyOfControlModeChange(int new_mode),
	NotifyOfConfigurationModeChange(Logical new_state);

ModeMask
	GetPresetModeMask()
		{
			Check(this);
			return previousPresetModeMask;
		}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Preset controls switching
//
void
	PresetEnable(int preset_number);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Protected data
//
protected:
	enum
	{
		presetCount = 6		// limited to number of switches!
	};

	ModeMask
		previousPresetModeMask;
	int
		previousPresetNumber;
};

//##########################################################################
//####################    ThrustmasterMapper    ############################
//##########################################################################

class VTVThrustmasterMapper:
	public L4VTVControlsMapper
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Shared Data Support
//
public:
	static Derivation *GetClassDerivations();
	static SharedData DefaultData;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Messaging Support
//
public:
	void
		KeypressMessageHandler(ReceiverDataMessageOf<ControlsKey> *message);

protected:
	static const HandlerEntry
		MessageHandlerEntries[];
	static MessageHandlerSet
		MessageHandlers;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Model Support
//
public:
	typedef void
		(VTVThrustmasterMapper::*Performance)(Scalar time_slice);

	void
		InterpretControls(Scalar time_slice);

	void
		SetPerformance(Performance performance)
			{
				Check(this);
				activePerformance = (Simulation::Performance)performance;
			}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction and Destruction Support
//
public:
	VTVThrustmasterMapper(
		VTV *player_vehicle,
		int subsystem_ID,
		SubsystemResource *subsystem_resource
	);
	~VTVThrustmasterMapper();

	Logical
  	TestInstance() const;

private:
	ControlsScalar
		leftPedal,
		rightPedal;
};

//##########################################################################
//###########################    RIOMapper    ##############################
//##########################################################################

class VTVRIOMapper :
	public L4VTVControlsMapper
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Shared Data Support
//
public:
	static Derivation *GetClassDerivations();
	static SharedData DefaultData;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Messaging Support
//
public:
	enum {
		SwitchModeMessageID = L4VTVControlsMapper::NextMessageID,
		SelectPresetMessageID,
		CenterJoystickMessageID,
		ConfigureControlsMessageID,	// duplicate of VTVControlsMapper msg
		NextMessageID
	};

	void
		KeypressMessageHandler(ReceiverDataMessageOf<ControlsKey> *message);
	void
		SwitchModeMessageHandler(
			ReceiverDataMessageOf<ControlsButton> *message
		);
	void
		SelectPresetMessageHandler(
			ReceiverDataMessageOf<ControlsButton> *message
		);
	void
		CenterJoystickMessageHandler(
			ReceiverDataMessageOf<ControlsButton> *message
		);
	void
		ConfigureControlsMessageHandler(
			ReceiverDataMessageOf<ControlsButton> *message
		);

protected:
	static const HandlerEntry
		MessageHandlerEntries[];
	static MessageHandlerSet
		MessageHandlers;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Model Support
//
public:
	typedef void
		(VTVRIOMapper::*Performance)(Scalar time_slice);

	void
		InterpretControls(Scalar time_slice);

	void
		NotifyOfControlModeChange(int new_mode);

	void
		NotifyOfConfigurationModeChange(Logical new_state);

	void
		SetPerformance(Performance performance)
			{
				Check(this);
				activePerformance = (Simulation::Performance)performance;
			}

	void
		AddOrErase(
			unsigned int button_ID,
			Receiver *target,
			Receiver::MessageID message_ID
		);

	void
		AddOrErase(
			unsigned int button_ID,
			ControlsButton *destination
		);
	void
		AddOrErase(
			unsigned int button_ID,
			Scalar *destination
		);

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction and Destruction Support
//
public:
	VTVRIOMapper(
		VTV *player_vehicle,
		int subsystem_ID,
		SubsystemResource *subsystem_resource
	);
	~VTVRIOMapper();

	Logical
		TestInstance() const;

protected:
	int
  	previousControlMode;

	enum
	{
		configLampCount=2,
		modeLampCount=4
	};

	L4Lamp
		*configLamp[configLampCount],
		*modeLamp[modeLampCount],
		*presetLamp[presetCount];

private:
	ControlsButton
		throttleUp,
		throttleDown,
		throttleReverse;

	ControlsScalar
		leftPedal,
		rightPedal;
};
