/*! \file pikbdlistener.h
 * \brief Keyboard console input listener
*/
/*
    PIP - Platform Independent Primitives
    Keyboard grabber for console
    Copyright (C) 2014  Ivan Pelipenko peri4ko@gmail.com

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef PIKBDLISTENER_H
#define PIKBDLISTENER_H

#include "pithread.h"
#ifndef WINDOWS
#  include <termios.h>
#endif

#define WAIT_FOR_EXIT while (!PIKbdListener::exiting) msleep(5);

typedef void (*KBFunc)(char, void * );

class PIP_EXPORT PIKbdListener: public PIThread
{
	PIOBJECT(PIKbdListener)
	friend class PIConsole;
public:
	
	//! Special keyboard keys
	enum SpecialSymbol {
		UpArrow /** Up arrow key */ = -1,
		DownArrow /** Down arrow key */ = -2,
		RightArrow /** Right arrow key */ = -3,
		LeftArrow /** Left arrow key */ = -4,
		CtrlUpArrow /** Ctrl + Up arrow key */ = -5,
		CtrlDownArrow /** Ctrl + Down arrow key */ = -6,
		CtrlRightArrow /** Ctrl + Right arrow key */ = -7,
		CtrlLeftArrow /** Ctrl + Left arrow key */ = -8
	};
	
	//! Constructs keyboard listener with external function "slot" and custom data "data"
	PIKbdListener(KBFunc slot = 0, void * data = 0);
	
	~PIKbdListener() {terminate(); end();}
	
	
	//! Returns custom data
	void * data() {return data_;}
	
	//! Set custom data to "_data"
	void setData(void * _data) {data_ = _data;}
	
	//! Set external function to "slot"
	void setSlot(KBFunc slot) {ret_func = slot;}
	
	//! Returns if exit key if awaiting
	bool exitCaptured() const {return exit_enabled;}
	
	//! Returns exit key, default 'Q'
	char exitKey() const {return exit_key;}
	
	
	//! Returns if keyboard listening is active (not running!)
	bool isActive() {return is_active;}
	
	EVENT_HANDLER( void, enableExitCapture) {enableExitCapture('Q');}
	EVENT_HANDLER1(void, enableExitCapture, char, key) {exit_enabled = true; exit_key = key;}
	EVENT_HANDLER(void, disableExitCapture) {exit_enabled = false;}
	EVENT_HANDLER(void, setActive) {setActive(true);}
	EVENT_HANDLER1(void, setActive, bool, yes);
	
	EVENT2(keyPressed, char, key, void * , data)
	
//! \handlers
//! \{
	
	//! \fn void enableExitCapture(char key = 'Q')
	//! \brief Enable exit key "key" awaiting
	
	//! \fn void disableExitCapture()
	//! \brief Disable exit key awaiting
	
	//! \fn void setActive(bool yes = true)
	//! \brief Set keyboard listening is active or not
	
//! \}
//! \events
//! \{
	
	//! \fn void keyPressed(char key, void * data)
	//! \brief Raise on key "key" pressed, "data" is custom data
	
//! \}
	
	static bool exiting;
	
private:
	void begin();
	void run();
	void end();
	
	KBFunc ret_func;
	char exit_key;
	bool exit_enabled, is_active;
	void * data_;
#ifdef WINDOWS
	DWORD ret, rc;
	void * hIn;
	DWORD smode, tmode;
#else
	int rc;
	int ret;
	struct termios sterm, tterm;
#endif

};

#endif // PIKBDLISTENER_H
