/*
 *  psychlops_io_keyboard.h
 *  Psychlops Standard Library (Universal)
 *
 *  Last Modified 2006/01/04 by Kenchi HOSOKAWA
 *  (C) 2006 Kenchi HOSOKAWA, Kazushi MARUYA and Takao SATO
 */

#ifndef HEADER_PSYCHLOPS_INPUT_HID
#define HEADER_PSYCHLOPS_INPUT_HID

#include "../graphic/psychlops_g_fundamental.h"


namespace Psychlops {

	class Keyboard;
	class Mouse;
	class HumanInterfaceDevice;
	class APIHIDProperties;
	typedef HumanInterfaceDevice Input;



	class Keyboard {
		friend class HumanInterfaceDevice;
		friend class APIHIDProperties;

		public:
		enum KeyState{
			pressed=0, pushed=1, released=2, hadpressed=3
		};
		struct Key {
			const int code;
			Key(const int code_);
			bool pressed() const;
			bool pushed() const;
			bool released() const;
			bool get(KeyState state) const;
		};
		static const Key
//		enum KeyCode{
			one,two,three,four,five,six,seven,eight,nine,zero,
			a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,
			comma,period,slash,
			pad0,pad1,pad2,pad3,pad4,pad5,pad6,pad7,pad8,pad9,
			rtn,spc,esc,tab,up,down,left,right,
			//	key modulator
			shift, shift_r, ctrl, alt,
			//  not recommended
			hyphen,equal,backslash,caret,
			underscore,semicolon,colon,leftbracket,rightbracket,at,   // because these keys laid on different location in differnt keyboard-lacalization.
			padcomma,padperiod,padenter,padplus,padminus,padasterisk,padslash,padequal,padclear,	//  because these keys are OS-specific.
			nfer,xfer   // because these keys exist only on Japanese keyboard
		;//};


		static void update();
		static void refresh();

		static bool get(Key key, KeyState state = pushed);

		//  obsolete
			static bool getKey(Key key, KeyState state = pushed);
			static void wait(Key key, bool needrelease=true);
			static void allReleased();

		protected:
		static void refresh_internal();
	};


	class Mouse {
		friend class HumanInterfaceDevice;
		friend class APIHIDProperties;
		static ::Psychlops::Point pointerPos, wheelDelta, lastPoint;

		public:
		enum ButtonState{
			pressed=0, pushed=1, released=2, hadpressed=3
		};
		struct Button {
			const int code;
			Button(const int code_);
			bool pressed() const;
			bool pushed() const;
			bool released() const;
			bool get(ButtonState state) const;
		};
		static const Button left, right, middle, any;

		class POSITION;
		struct POSITIONVAL {
			friend class POSITION;
			friend class Mouse;
			friend class APIHIDProperties;
			protected:
			int val_;

			public:
			POSITIONVAL();
			operator int();
			int operator =(int val);
		};
		static POSITIONVAL uniX, uniY;
		struct POSITION { public: operator Psychlops::Point(); Psychlops::Point operator =(Point val); };
		static POSITION uniPosition;

		struct DEFPOSITIONVALX { operator int(); int operator =(int val); };
		static DEFPOSITIONVALX x;
		struct DEFPOSITIONVALY { operator int(); int operator =(int val); };
		static DEFPOSITIONVALY y;
		struct DEFPOSITION { operator ::Psychlops::Point(); ::Psychlops::Point operator =(::Psychlops::Point val); };
		static DEFPOSITION position;

		static bool show_local_pointer_;
		static bool showLocalPointer();

		static void initialize();

		static void update();
		static void refresh();

		static bool get(Button code, ButtonState state = pushed);
		static ::Psychlops::Point getWheelDelta();

		static void show();
		static void hide();
		static void drawPointer(Point p, Drawable &target);
		static void setPointer(int size);
		static void setPointer(Figure &fig);
		static Figure* pointer_figure;

		protected:
		static void refresh_internal();
	};

	class APIMouseProperties;
	class HumanInterfaceDevice {
		friend class Keyboard;
		friend class Mouse;
		friend class APIHIDProperties;
		friend class APIMouseProperties;

	public:
		enum ButtonState {
			pressed=0, pushed=1, released=2, hadpressed=3
		};
		struct ButtonStateHolder {
		private:
			Mouse::Button *target;
			bool pressed_, pushed_, released_, hadpressed_;
			void ask();
		public:
			ButtonStateHolder(const Mouse::Button &);
			bool pressed();
			bool pushed();
			bool released();
		};
	private:
		static bool runningHIDListner;
		struct States {
			bool key[128];
			bool button[8];
			bool gamepad[32];
		};
		static States state[3];

	public:
		static void initialize();
		static void finalize();

		static void startListener();
		static void stopListener();

		static void refresh();

		static bool get(Keyboard::Key code, Keyboard::KeyState state = Keyboard::pushed);
		static bool get(Mouse::Button code, Mouse::ButtonState state = Mouse::pushed);
		static void wait(Keyboard::Key code, Keyboard::KeyState state = Keyboard::pushed);
	};




}	/*	<- namespace Psycholops 	*/

#endif
