#pragma once

#include "controls.hpp"

namespace Adept
{
	//#########################################################################
	//#####################    CControlMappingList    #########################
	//#########################################################################
	class CControlMappingList
	{
		private:
			stlport::vector<ControlData> m_Mappings;

			struct ControlDef
			{
				ControlDef();
				~ControlDef();

				//stlport::vector<ControlData>::iterator iter[3];  //save "pointer" into mappings vector for key,mouse,joy
				//  I'll keep the three original copies around for reconstruction if needed
				ControlData		cd_key;
				bool			cd_key_valid;
				ControlData		cd_joy;
				bool			cd_joy_valid;
				ControlData		cd_mouse;
				bool			cd_mouse_valid;

				int  mesg_id;		//unique id of command (-1 if category heading)
				int  nameresid;		//resource id of command name
				int  control_type;	//category (fire,move,misc,lancemate)
				int  control_mask;	//keyboard ctrl/alt/shift bit values
				int  nKey;			//key id
				int  nMouse;		//mouse button id
				int  nJoy;			//joystick button id
				int  nIdx;			//index in gosScript list (adjusted for category)

				const char* KeyName() const;
				const char* JoyName() const;
				const char* MouseName() const;

				private:
				ControlDef(const ControlDef&);				// not defined
				ControlDef& operator=(const ControlDef&);	// not defined

			};

			int m_nCount;
			ControlDef *m_pcdHead;
			bool m_fInvertJoyY;
			bool m_fInvertMouseY;
			int	 m_joystickButtons;

			int m_Joystick;					// id of the joystick being used for mappings.

			bool m_ForceFeedBack;
			Scalar m_MouseSensitivity;

			bool m_joyStickAllowed;
			bool m_mouseAllowed;
			int m_joyStickShiftValue;
			
			Stuff::Scalar m_joystick_throttle_center;
			Stuff::Scalar m_joystick_throttle_dead_low;
			Stuff::Scalar m_joystick_throttle_dead_high;

			int m_JoystickXAxisType;
			int m_JoystickRudderAxisType;
			int m_MouseXAxisType;

			static int compareControls(const void *elem1, const void *elem2);
			void SetInvertStateOfList();
			void GetInvertStateOfList();
			CControlMappingList (const CControlMappingList&);	// not defined
			CControlMappingList& operator=(const CControlMappingList&);	// not defined
			
			bool AxisButtonUsed (int group,int element);

		public:
			enum {
				NONE_AXIS,
				TURNING_AXIS,
				TORSO_AXIS
			};

			CControlMappingList (const char *filename,Entity::ClassData *classdata);
			CControlMappingList (const ResourceID& control_stream);
			CControlMappingList (void);
			~CControlMappingList (void);

			void Joystick(int id, Plug* owner);
			int Joystick() const			{ return m_Joystick; }

			void JoystickXAxis (int value, Plug* owner);
			int JoystickXAxis (void) const
			{ return m_JoystickXAxisType; }
			
			void JoystickRudderAxis (int value, Plug* owner);
			int JoystickRudderAxis (void) const
			{ return m_JoystickRudderAxisType; }
			
			void MouseXAxis (int value, Plug* owner);
			int MouseXAxis (void) const
			{ return m_MouseXAxisType; }

			bool IsJoyYInverted() const		{ return m_fInvertJoyY; }
			void SetJoyYInvert(bool b, Plug* owner);

			bool IsMouseYInverted() const	{ return m_fInvertMouseY; }
			void SetMouseYInvert(bool b, Plug* owner);

			bool IsMouseAllowed() const		{ return m_mouseAllowed; }
			void SetMouseAllowed(bool b, Plug*);

			bool IsJoyStickAllowed() const	{ return m_joyStickAllowed; }
			void SetJoyStickAllowed(bool b, Plug*);

			bool IsJoyStickShiftAllowed() const {return m_joyStickShiftValue != -1;}
			int SetJoyStickShiftAllowed(bool b, Plug*, int* retIndex1, int* retIndex2);

			int GetJoyStickShiftValue() const	{return m_joyStickShiftValue;}
			int SetJoyStickShiftValue(int n, Plug*, int* retIndex1, int* retIndex2);

			Scalar JoyStickThrottleCenter() const	{return m_joystick_throttle_center;}
			void JoyStickThrottleCenter(Scalar s, Plug*);
			Scalar JoyStickThrottleLow() const	{return m_joystick_throttle_dead_low;}
			void JoyStickThrottleLow(Scalar s, Plug*);
			Scalar JoyStickThrottleHigh() const	{return m_joystick_throttle_dead_high;}
			void JoyStickThrottleHigh(Scalar s, Plug*);
			void InitializeThrottleConstants();

			bool ForceFeedBack (void) const
			{ return m_ForceFeedBack; }
			void ForceFeedBack (bool value, Plug* owner);
			Scalar MouseSensitivity (void) const
			{ return m_MouseSensitivity; }
			void MouseSensitivity (Scalar value, Plug* owner);


			void SaveList (const ResourceID& control_stream);
			void SaveList (MemoryStream& res);
			void LoadList (const char *filename,Entity::ClassData *classdata);
			void LoadList (const ResourceID& control_stream);
			void LoadList (MemoryStream& resource_locker);
			void LoadDefault (void);
			void ApplyList (Plug *owner);

			int  GetList(bool fRestoreDefaults);
			void SetList(Plug* owner);
			void FillDefault (stlport::vector<ControlData>& list);

			stlport::vector<ControlData>::iterator StartList (void);
			stlport::vector<ControlData>::iterator EndList (void);

			void ReplaceList (stlport::vector<ControlData>::iterator start,stlport::vector<ControlData>::iterator end);
			stlport::vector<ControlData> &List (void)
			{ return m_Mappings; }

			int		DefListSize() const		{return m_nCount;}
			const ControlDef& GetControlDef(int i) const	{return m_pcdHead[i];}

			int	AssignControlKey(Plug* owner, int nRow, int newKey, int newModifiers);
			int	AssignControlJoy(Plug* owner, int nRow, int newJoy, int shift);
			int	AssignControlMouse(Plug* owner, int nRow, int newMouse);
	};

	extern CControlMappingList *g_ControlList;
};


//Adept::CControlsMappingList::ControlDef foo;
