// *** OpenGTA3 ***
// input events

// internal keycode values
enum RsKeyCode {
	rsESC		= 0x3E8,
	rsF1		= 0x3E9,
	rsF2		= 0x3EA,
	rsF3		= 0x3EB,
	rsF4		= 0x3EC,
	rsF5		= 0x3ED,
	rsF6		= 0x3EE,
	rsF7		= 0x3EF,
	rsF8		= 0x3F0,
	rsF9		= 0x3F1,
	rsF10		= 0x3F2,
	rsF11		= 0x3F3,
	rsF12		= 0x3F4,
	rsINSERT	= 0x3F5,
	rsDEL		= 0x3F6,
	rsHOME		= 0x3F7,
	rsEND		= 0x3F8,
	rsPGUP		= 0x3F9,
	rsPGDN		= 0x3FA,
	rsUP		= 0x3FB,
	rsDOWN		= 0x3FC,
	rsLEFT		= 0x3FD,
	rsRIGHT		= 0x3FE,
	rsDIV		= 0x3FF,	// keypad '/'
	rsMUL		= 0x400,	// keypad '*'
	rsADD		= 0x401,	// keypad '+'
	rsSUB		= 0x402,	// keypad '-'
	rsEXTDEL	= 0x403,
	rsDECIMAL	= 0x403,
	rsEXTEND	= 0x404,
	rsNUM1		= 0x404,
	rsEXTDOWN	= 0x405,
	rsNUM2		= 0x405,
	rsEXTPGDN	= 0x406,
	rsNUM3		= 0x406,
	rsEXTLEFT	= 0x407,
	rsNUM4		= 0x407,
	rsNUM5		= 0x408,
	rsNUMLOCK	= 0x409,
	rsEXTRIGHT	= 0x40A,
	rsNUM6		= 0x40A,
	rsEXTHOME	= 0x40B,
	rsNUM7		= 0x40B,
	rsEXTUP		= 0x40C,
	rsNUM8		= 0x40C,
	rsEXTPGUP	= 0x40D,
	rsNUM9		= 0x40D,
	rsEXTINSERT = 0x40E,
	rsNUM0		= 0x40E,
	rsENTER		= 0x40F,
	rsSCROLL	= 0x410,
	rsPAUSE		= 0x411,
	rsBACK		= 0x412,
	rsTAB		= 0x413,
	rsCAPSLOCK	= 0x414,
	rsEXTENTER	= 0x415,
	rsLSHIFT	= 0x416,
	rsRSHIFT	= 0x417,
	rsSHIFT		= 0x418,
	rsLCTRL		= 0x419,
	rsRCTRL		= 0x41A,
	rsLMENU		= 0x41B,
	rsRMENU		= 0x41C,
	rsLWIN		= 0x41D,
	rsRWIN		= 0x41E,
	rsAPPS		= 0x41F,
	rsNULL		= 0x420
};

enum RsMouseButtons {
	rsLMB		= 0,
	rsRMB		= 1,
	rsMMB		= 2,
	rsWHEELUP	= 3,
	rsWHEELDOWN	= 4,
	rsBMX1		= 5,
	rsBMX2		= 6,
	rsMBNONE	= 7	// 
};
enum InputEvent {
	evPED_FIREWEAPON			= 0,
	evPED_FIREWEAPON_ALT		= 1,
	evPED_CYCLE_WEAPON_RIGHT	= 2,
	evPED_CYCLE_WEAPON_LEFT		= 3,
	evGO_FORWARD				= 4,
	evGO_BACK					= 5,
	evGO_LEFT					= 6,
	evGO_RIGHT					= 7,
	evPED_SNIPER_ZOOM_IN		= 8,
	evPED_SNIPER_ZOOM_OUT		= 9,
	evVEHICLE_ENTER_EXIT		= 10,
	evCAMERA_CHANGE_VIEW_ALL_SITUATIONS	= 11,
	evPED_JUMPING				= 12,
	evPED_SPRINT				= 13,
	evPED_LOOKBEHIND			= 14,
	evPED_DUCK					= 15,
	evPED_ANSWER_PHONE			= 16,
	evSNEAK_ABOUT				= 17,
	evVEHICLE_FIREWEAPON		= 18,
	evVEHICLE_FIREWEAPON_ALT	= 19,
	evVEHICLE_STEERLEFT			= 20,
	evVEHICLE_STEERRIGHT		= 21,
	evVEHICLE_STEERUP			= 22,
	evVEHICLE_STEERDOWN			= 23,
	evVEHICLE_ACCELERATE		= 24,
	evVEHICLE_BRAKE				= 25,
	evVEHICLE_RADIO_STATION_UP	= 26,
	evVEHICLE_RADIO_STATION_DOWN= 27,
	evVEHICLE_HORN				= 29,
	evTOGGLE_SUBMISSIONS		= 30,
	evVEHICLE_HANDBRAKE			= 31,
	evPED_1RST_PERSON_LOOK_LEFT	= 32,
	evPED_1RST_PERSON_LOOK_RIGHT= 33,
	evVEHICLE_LOOKLEFT			= 34,
	evVEHICLE_LOOKRIGHT			= 35,
	evVEHICLE_LOOKBEHIND		= 36,
	evVEHICLE_MOUSELOOK			= 37,
	evVEHICLE_TURRETLEFT		= 38,
	evVEHICLE_TURRETRIGHT		= 39,
	evVEHICLE_TURRETUP			= 40,
	evVEHICLE_TURRETDOWN		= 41,
	evPED_CYCLE_TARGET_LEFT		= 42,
	evPED_CYCLE_TARGET_RIGHT	= 43,
	evPED_CENTER_CAMERA_BEHIND_PLAYER	= 44,
	evPED_LOCK_TARGET			= 45,
	evNETWORK_TALK				= 46,
	evCONVERSATION_YES			= 47,
	evCONVERSATION_NO			= 48,
	evGROUP_CONTROL_FWD			= 49,
	evGROUP_CONTROL_BWD			= 50,
	evPED_1RST_PERSON_LOOK_UP	= 51,
	evPED_1RST_PERSON_LOOK_DOWN	= 52,
	evTOGGLE_DPAD				= 54,
	evSWITCH_DEBUG_CAM_ON		= 55,
	evTAKE_SCREEN_SHOT			= 56,
	evSHOW_MOUSE_POINTER_TOGGLE	= 57,
	evLAST	= 0x7FFFFFFF
};

#define EVENT_COUNT	59

#pragma pack(push,1)

// keyboard scan results
// NOTE: this structure is different from original ingame structure
struct KeyState {
	WORD	stdKeys[256];	
	WORD	extKeys[56];	// rsESC-rsNULL, access as extKeys[keycode-rsESC];
};

struct MouseState {
	BYTE	buttons[8];
	float	_f8;
	float	_fC;
	float	_f10;
};

struct PadState {
	BYTE	_0[0x30];	// 000 -
	BYTE	buttons[16];// 030
	BYTE	_40[0xD0];	// 040 -
};

class CInputEvents {
public:
	
	void	initEventNames ();	// >> 52D260 (1)
	void	initPriority (InputEvent event);	// >> 52F5F0 (3/5)
	void	initEvent (InputEvent event, DWORD type);// >> 52FD70	(59)

	bool	isKeyPressed (RsKeyCode key);	// >> 52DDB0 (4)
	bool	isKeyJustPressed (RsKeyCode key);	// >> 52E450 (5)

	int		getPadButtonJustPressed ();	// >> 52D1E0 (2)
	

	void mapEvent (InputEvent event, RsKeyCode keycode, DWORD type); // >> 530490 (141)
	void init (); // >> 530500 (3)

	void writeToSettings (DWORD * data);	//	>> 52D200 (modified)
	bool readFromSettings (DWORD * data);	// 

	struct Event {
		DWORD keycode;
		DWORD priority;
	};

	BYTE		_f0;
	BYTE		_f1;
	BYTE		_f2;
	BYTE		_f3;
	PadState	currPadState;
	PadState	prevPadState;
	char		eventNames[EVENT_COUNT][40];
	DWORD		_fB5C;
	DWORD		_fB60;
	DWORD		_fB64;
	DWORD		_fB68;
	BYTE		_fB6C;
	BYTE		_align[3];
	Event		events[EVENT_COUNT][4];
	BYTE		_f12D0[16];
	BYTE		_f12E0;
	BYTE		_align2[3];
};

// TODO: вообще-то структура должна называться PlayerInputData, т.к. для пада в ней хранятся аналоговые значения
// TODO: переименовать поля
struct PlayerKeysData {
	WORD	keys[24];
};

struct CPlayerControlData {

	void init (BYTE a0, BYTE a4); // >> 541A70 (14)

	PlayerKeysData	_f0;	// 000
	PlayerKeysData	_f30;	// 030
	DWORD			_f60;	// 060
	DWORD			_f64;	// 064
	DWORD			_f68;	// 068
	DWORD			_f6C;	// 06C
	DWORD			_f70;	// 070
	DWORD			_f74;	// 074
	PlayerKeysData	_f78;	// 078
	PlayerKeysData	_fA8;	// 0A8
	PlayerKeysData	_fD8;	// 0D8
	BYTE			_f108;	// 108
	BYTE			_f109;	// 109
	WORD			_f10A;	// 10A (state 0..3)
	WORD			_f10C;	// 10C
	WORD			_f10E;	// 10E
	BYTE			_f110;	// 110
	DWORD			_f111;	// 111
	BYTE			_f115;	// 115
	BYTE			_f116;	// 116
	BYTE			_f117;	// 117
	BYTE			_f118;	// 118
	BYTE			_f119;	// 119
	BYTE			_f11A;	// 11A
	BYTE			_f11B;	// 11B
	BYTE			_f11C;	// 11C
	BYTE			_f11D;	// 11D
	BYTE			_f11E;	// 11E
	BYTE			_f11F;	// 11F
	DWORD			_f120;	// 120
	DWORD			_f124;	// 124
	DWORD			_f128;	// 128
	DWORD			_f12C;	// 12C
	BYTE			_f130;	// 130
	BYTE			_f131;	// 131
	WORD			_f132;	// 132
};
#pragma pack(pop)

extern CInputEvents * inputEvents;	// TODO: make as static object
extern CPlayerControlData * playerControlData;

extern KeyState	activeKeyState;	
extern KeyState	currKeyState;
extern KeyState	prevKeyState;

extern MouseState * activeMouseState;
extern MouseState * currMouseState;
extern MouseState * prevMouseState;

// global functions
void processCheatcodes ();	// >> 439AF0
bool isEnterJustPressed (); // >> 4D5980 (1) TODO: originally, CPlayerControlData::isEnterJustPressed
bool isStdKeyJustPressed (); // >> 4D59B0 (1)
bool isNeedSkipCutscene (); // >> 4D5D10 (3)
bool isEscJustPressed (); // >> 572DB0 (3) TODO: originally, CPlayerControlData::isEnterJustPressed

void initKeyStates (); // >> 53F1E0 (2)
RsKeyCode * getKeyJustPressed (RsKeyCode * key); // >> 541490 (1) TODO: move to InputEvents

// main input processing function
void processInput (); // >> 541DD0 (1:processGame)