#include "IEventReceiver.h"
using namespace irr;

//! Any kind of GUI event.
class MyGUIEvent
{
	SEvent* original;
public:
	MyGUIEvent(SEvent* val)
	:original(val)
	{
	}
	
	//! IGUIElement who called the event
	irr::gui::IGUIElement* getCaller()
	{
		return original->GUIEvent.Caller;
	}
	void setCaller(irr::gui::IGUIElement* val)
	{
		original->GUIEvent.Caller = val;
	}
	
	//! If the event has something to do with another element, it will be held here.
	irr::gui::IGUIElement* getElement()
	{
		return original->GUIEvent.Element;
	}
	void setElement(irr::gui::IGUIElement* val)
	{
		original->GUIEvent.Element = val;
	}
	
	//! Type of GUI Event
	irr::gui::EGUI_EVENT_TYPE getEventType()
	{
		return original->GUIEvent.EventType;
	}
	void setEventType(irr::gui::EGUI_EVENT_TYPE val)
	{
		original->GUIEvent.EventType = val;
	}
};

//! Any kind of mouse event.
class MyMouseInput
{
	SEvent* original;
public:
	MyMouseInput(SEvent* val)
	:original(val)
	{
	}

	//! X position of mouse cursor
	s32 getX()
	{
		return original->MouseInput.X;
	}
	void setX(s32 val)
	{
		original->MouseInput.X = val;
	}

	//! Y position of mouse cursor
	s32 getY()
	{
		return original->MouseInput.Y;
	}
	void setY(s32 val)
	{
		original->MouseInput.Y = val;
	}
	
	//! mouse wheel delta, usually 1.0 or -1.0.
	/** Only valid if event was EMIE_MOUSE_WHEEL */
	f32 getWheel()
	{
		return original->MouseInput.Wheel;
	}
	void setWheel(f32 val)
	{
		original->MouseInput.Wheel = val;
	}
	
	//! Type of mouse event
	EMOUSE_INPUT_EVENT getEvent()
	{
		return original->MouseInput.Event;
	}
	void setEvent(EMOUSE_INPUT_EVENT val)
	{
		original->MouseInput.Event = val;
	}
};

//! Any kind of keyboard event.
class MyKeyInput
{
	SEvent* original;
public:
	MyKeyInput(SEvent* val)
	:original(val)
	{
	}
	//! Character corresponding to the key (0, if not a character)
	wchar_t getChar()
	{
		return original->KeyInput.Char;
	}
	void setChar(wchar_t val)
	{
		original->KeyInput.Char = val;
	}
	
	//! Key which has been pressed or released
	EKEY_CODE getKey()
	{
		return original->KeyInput.Key;
	}
	void setKey(EKEY_CODE val)
	{
		original->KeyInput.Key = val;
	}
	
	//! If not true, then the key was left up
	bool getPressedDown()
	{
		return original->KeyInput.PressedDown;
	}
	void setPressedDown(bool val)
	{
		original->KeyInput.PressedDown = val;
	}
	
	//! True if shift was also pressed
	bool getShift()
	{
		return original->KeyInput.Shift;
	}
	void setShift(bool val)
	{
		original->KeyInput.Shift = val;
	}
	
	//! True if ctrl was also pressed
	bool getControl()
	{
		return original->KeyInput.Control;
	}
	void setControl(bool val)
	{
		original->KeyInput.Control = val;
	}
};

//! A joystick event.
/** Unlike other events, joystick events represent the result of polling 
 * each connected joystick once per run() of the device. Joystick events will
 * not be generated by default.  If joystick support is available for the 
 * active device, _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ is defined, and 
 * @ref IrrlichtDevice::activateJoysticks() has been called, an event of 
 * this type will be generated once per joystick per @ref IrrlichtDevice::run() 
 * regardless of whether the state of the joystick has actually changed. */
class MyJoystickEvent
{
	SEvent* original;
public:
	MyJoystickEvent(SEvent* val)
	:original(val)
	{
	}

	enum
	{
		NUMBER_OF_BUTTONS = 32,

		AXIS_X = 0, // e.g. analog stick 1 left to right
		AXIS_Y,		// e.g. analog stick 1 top to bottom
		AXIS_Z,		// e.g. throttle, or analog 2 stick 2 left to right
		AXIS_R,		// e.g. rudder, or analog 2 stick 2 top to bottom
		AXIS_U,
		AXIS_V,
		NUMBER_OF_AXES
	};

	/** A bitmap of button states.  You can use IsButtonPressed() to
	 ( check the state of each button from 0 to (NUMBER_OF_BUTTONS - 1) */
	u32 getButtonStates()
	{
		return original->JoystickEvent.ButtonStates;
	}
	void setButtonStates(u32 val)
	{
		original->JoystickEvent.ButtonStates = val;
	}
	
	/** The POV represents the angle of the POV hat in degrees * 100, 
	 * from 0 to 35,900.  A value of 65535 indicates that the POV hat 
	 * is centered (or not present).
	 * This value is only supported on Windows.  On Linux, the POV hat
	 * will be sent as 2 axes instead. */
	u16 getPOV()
	{
		return original->JoystickEvent.POV;
	}
	void setPOV(u16 val)
	{
		original->JoystickEvent.POV = val;
	}
	
	//! The ID of the joystick which generated this event.
	/** This is an internal Irrlicht index; it does not map directly
	 * to any particular hardware joystick. */
	u8 getJoystick()
	{
		return original->JoystickEvent.Joystick;
	}
	void setJoystick(u8 val)
	{
		original->JoystickEvent.Joystick = val;
	}
	
	//! A helper function to check if a button is pressed.
	bool IsButtonPressed(u32 button)
	{
		if(button >= (u32)NUMBER_OF_BUTTONS)
			return false;

		return (getButtonStates() & (1 << button)) ? true : false;
	}
	
	/** For AXIS_X, AXIS_Y, AXIS_Z, AXIS_R, AXIS_U and AXIS_V
	 * Values are in the range -32768 to 32767, with 0 representing
	 * the center position.  You will receive the raw value from the 
	 * joystick, and so will usually want to implement a dead zone around 
	 * the center of the range. Axes not supported by this joystick will 
	 * always have a value of 0. On Linux, POV hats are represented as axes, 
	 * usually the last two active axis.
	 */
	short GetAxis(int buttonNo)
	{
		return original->JoystickEvent.Axis[buttonNo];
	}
	void SetAxis(int buttonNo, short value)
	{
		original->JoystickEvent.Axis[buttonNo] = value;
	}
};


//! Any kind of log event.
class MyLogEvent
{
	SEvent* original;
public:
	MyLogEvent(SEvent* val)
	:original(val)
	{
	}
	//! Pointer to text which has been logged
	const c8* getText()
	{
		return original->LogEvent.Text;
	}
	void setText(const c8* val)
	{
	}
	
	//! Log level in which the text has been logged
	ELOG_LEVEL getLevel()
	{
		return original->LogEvent.Level;
	}
	void setLevel(ELOG_LEVEL val)
	{
		original->LogEvent.Level = val;
	}
};

//! Any kind of user event.
struct MyUserEvent
{
	SEvent* original;
public:
	MyUserEvent(SEvent* val)
	:original(val)
	{
	}
	//! Some user specified data as int
	s32 getUserData1()
	{
		return original->UserEvent.UserData1;
	}
	void setUserData1(s32 val)
	{
		original->UserEvent.UserData1 = val;
	}
	
	//! Another user specified data as int
	s32 getUserData2()
	{
		return original->UserEvent.UserData2;
	}
	void setUserData2(s32 val)
	{
		original->UserEvent.UserData2 = val;
	}
};
//
//#ifdef SWIG
//typedef bool (* EVENTCALLBACK)(int);
//#else
//typedef bool (__stdcall* EVENTCALLBACK)(int);
//#endif
//class EventReciever : public irr::IEventReceiver
//{
//	EVENTCALLBACK _callback;
//	const irr::SEvent* _ev;
//public:
//	EventReciever(EVENTCALLBACK eventReceivedCallback)
//	{
//		_callback = eventReceivedCallback;
//	}
//	irr::SEvent GetEventData()
//	{
//		return *_ev;
//	}
//	virtual bool OnEvent(const irr::SEvent& ev)
//	{
//		_ev = &ev;
//		return _callback(0);
//	}
//};
//
//extern "C"
//{
//int CreateEventReciever(EVENTCALLBACK eventReceivedCallback)
//{
//	return (int)(new EventReciever(eventReceivedCallback));
//}
//}
//
//EventReciever* TransrateEventReceiver(int var)
//{
//	return (EventReciever*)var;
//}

typedef irr::core::rect<s32> rectInt;

