/*
	Ripatti Artem (c) 2013
*/

#define _CRT_SECURE_NO_WARNINGS

#include "ie_fltk_1_3.h"
#include "log.h"

namespace ie
{
	InputEngineFLTK13::InputEngineFLTK13()
	{
		mx = my = mx0 = my0 = 0;
		memset( diks, 0, sizeof(diks) );
		memset( diks2, 0, sizeof(diks2) );
		memset( diks0, 0, sizeof(diks0) );

		memset( btn, 0, sizeof(btn) );
		memset( btn2, 0, sizeof(btn2) );
		memset( btn0, 0, sizeof(btn0) );

		char str[] = "abcdefghijklmnopqrstuvwxyz1234567890-=[];',./\\ ";
		int codez[] = {
			DIK_A, DIK_B, DIK_C, DIK_D, DIK_E, DIK_F, DIK_G, DIK_H, DIK_I, DIK_J,
			DIK_K, DIK_L, DIK_M, DIK_N, DIK_O, DIK_P, DIK_Q, DIK_R, DIK_S, DIK_T,
			DIK_U, DIK_V, DIK_W, DIK_X, DIK_Y, DIK_Z,
			DIK_1, DIK_2, DIK_3, DIK_4, DIK_5, DIK_6, DIK_7, DIK_8, DIK_9, DIK_0,
			DIK_MINUS, DIK_EQUALS, DIK_LBRACKET, DIK_RBRACKET, DIK_SEMICOLON,
			DIK_APOSTROPHE, DIK_COMMA, DIK_PERIOD, DIK_SLASH, DIK_BACKSLASH, DIK_SPACE
		};
		int sz = (int)strlen( str );

		for (int a=0; a<sz; a++)
			fl_to_dik[(int)str[a]] = codez[a];

		fl_to_dik[FL_BackSpace]		= DIK_BACKSPACE;
		fl_to_dik[FL_Tab]			= DIK_TAB;
		fl_to_dik[FL_Enter]			= DIK_RETURN;
		fl_to_dik[FL_Pause]			= DIK_PAUSE;
		fl_to_dik[FL_Scroll_Lock]	= DIK_SCROLL;
		fl_to_dik[FL_Escape]		= DIK_ESCAPE;
		fl_to_dik[FL_Home]			= DIK_HOME;
		fl_to_dik[FL_Left]			= DIK_LEFT;
		fl_to_dik[FL_Up]			= DIK_UP;
		fl_to_dik[FL_Right]			= DIK_RIGHT;
		fl_to_dik[FL_Down]			= DIK_DOWN;
		fl_to_dik[FL_Page_Up]		= DIK_PGUP;
		fl_to_dik[FL_Page_Down]		= DIK_PGDN;
		fl_to_dik[FL_End]			= DIK_END;
		//FL_Print	0xff61	///< The print (or print-screen) key.
		fl_to_dik[FL_Insert]		= DIK_INSERT;
		//FL_Menu		0xff67	///< The menu key.
		//FL_Help		0xff68	///< The 'help' key on Mac keyboards
		//FL_Num_Lock	0xff7f	///< The num lock key.
		//FL_KP		0xff80	///< One of the keypad numbers; use FL_KP + n for number n.
		//FL_KP_Enter	0xff8d	///< The enter key on the keypad, same as Fl_KP+'\\r'.
		//FL_KP_Last	0xffbd	///< The last keypad key; use to range-check keypad.
		//FL_F		0xffbd	///< One of the function keys; use FL_F + n for function key n.
		//FL_F_Last	0xffe0	///< The last function key; use to range-check function keys.
		for (int a=1; a<=10; a++)
			fl_to_dik[FL_F+a]		= DIK_F1 + a - 1;
		fl_to_dik[FL_Shift_L]		= DIK_LSHIFT;
		fl_to_dik[FL_Shift_R]		= DIK_RSHIFT;
		fl_to_dik[FL_Control_L]		= DIK_LCONTROL;
		fl_to_dik[FL_Control_R]		= DIK_RCONTROL;
		fl_to_dik[FL_Caps_Lock]		= DIK_CAPSLOCK;
		//FL_Meta_L	0xffe7	///< The left meta/Windows key.
		//FL_Meta_R	0xffe8	///< The right meta/Windows key.
		fl_to_dik[FL_Alt_L]			= DIK_LALT;
		fl_to_dik[FL_Alt_R]			= DIK_RALT;
		fl_to_dik[FL_Delete]		= DIK_DELETE;
	}

	InputEngineFLTK13::~InputEngineFLTK13()
	{
	}

	int InputEngineFLTK13::outer_handle(Fl_Window * wnd, int e)
	{
		if ( e == FL_MOVE || e == FL_DRAG )
		{
			mx0 = Fl::event_x();
			my0 = Fl::event_y();
		}

		if ( e == FL_PUSH )
		{
			if (Fl::event_button() == FL_LEFT_MOUSE)
				btn0[0] = true;
			else if (Fl::event_button() == FL_RIGHT_MOUSE)
				btn0[1] = true;
			return 1;
		}

		if ( e == FL_RELEASE )
		{
			if (Fl::event_button() == FL_LEFT_MOUSE)
				btn0[0] = false;
			else if (Fl::event_button() == FL_RIGHT_MOUSE)
				btn0[1] = false;
			return 1;
		}

		if ( e == FL_KEYDOWN )
		{
			if (fl_to_dik.find( Fl::event_original_key() ) != fl_to_dik.end())
				diks0[ fl_to_dik[ Fl::event_original_key() ] ] = true;

			return 1;
		}

		if ( e == FL_KEYUP )
		{
			if (fl_to_dik.find( Fl::event_original_key() ) != fl_to_dik.end())
				diks0[ fl_to_dik[ Fl::event_original_key() ] ] = false;

			return 1;
		}

		return 0;
	}

	void InputEngineFLTK13::clear_states()
	{
		memset( diks, 0, sizeof( diks ) );
		memset( diks2, 0, sizeof( diks2 ) );

		memset( btn, 0, sizeof( btn ) );
		memset( btn2, 0, sizeof( btn2 ) );
	}

	void InputEngineFLTK13::read_states()
	{
		mx = mx0;
		my = my0;

		for (int a=0; a<256; a++)
		{
			diks2[a] = diks[a];
			diks[a] = diks0[a];
		}

		for (int a=0; a<4; a++)
		{
			btn2[a] = btn[a];
			btn[a] = btn0[a];
		}
	}

	bool InputEngineFLTK13::pressed(int key, bool before, bool now)
	{
		if (key<0 || key>=256) return false;
		return (diks2[key])==before && (diks[key])==now;
	}

	bool InputEngineFLTK13::pressed_before(int key)
	{
		if (key<0 || key>=256) return false;
		return (diks2[key]);
	}

	bool InputEngineFLTK13::pressed_now(int key)
	{
		if (key<0 || key>=256) return false;
		return (diks[key]);
	}

	int InputEngineFLTK13::get_mouse_x()
	{
		return mx;
	}

	int InputEngineFLTK13::get_mouse_y()
	{
		return my;
	}

	bool InputEngineFLTK13::mouse_pressed(int button, bool before, bool now)
	{
		if (button<0 || button>=4) return false;
		return (btn2[button])==before && (btn[button])==now;
	}

	bool InputEngineFLTK13::mouse_pressed_before(int button)
	{
		if (button<0 || button>=4) return false;
		return (btn2[button]);
	}

	bool InputEngineFLTK13::mouse_pressed_now(int button)
	{
		if (button<0 || button>=4) return false;
		return (btn[button]);
	}
};