#ifndef K3DSDK_KEYBOARD_H
#define K3DSDK_KEYBOARD_H

#include "custom_marshallers.h"
#include "signal_system.h"

#include <bitset>
#include <iosfwd>

namespace k3d
{

// Forward declarations
class icommand_node;

class key_modifiers
{
public:
	key_modifiers& set();
	key_modifiers& set_shift(bool val = true);
	key_modifiers& set_lock(bool val = true);
	key_modifiers& set_control(bool val = true);
	key_modifiers& set_mod1(bool val = true);
	key_modifiers& set_mod2(bool val = true);
	key_modifiers& set_mod3(bool val = true);
	key_modifiers& set_mod4(bool val = true);
	key_modifiers& set_mod5(bool val = true);
	key_modifiers& set_button1(bool val = true);
	key_modifiers& set_button2(bool val = true);
	key_modifiers& set_button3(bool val = true);
	key_modifiers& set_button4(bool val = true);
	key_modifiers& set_button5(bool val = true);
	key_modifiers& set_release(bool val = true);
	
	key_modifiers& reset();
	key_modifiers& reset_shift();
	key_modifiers& reset_lock();
	key_modifiers& reset_control();
	key_modifiers& reset_mod1();
	key_modifiers& reset_mod2();
	key_modifiers& reset_mod3();
	key_modifiers& reset_mod4();
	key_modifiers& reset_mod5();
	key_modifiers& reset_button1();
	key_modifiers& reset_button2();
	key_modifiers& reset_button3();
	key_modifiers& reset_button4();
	key_modifiers& reset_button5();
	key_modifiers& reset_release();
	
	key_modifiers& flip();
	key_modifiers& flip_shift();
	key_modifiers& flip_lock();
	key_modifiers& flip_control();
	key_modifiers& flip_mod1();
	key_modifiers& flip_mod2();
	key_modifiers& flip_mod3();
	key_modifiers& flip_mod4();
	key_modifiers& flip_mod5();
	key_modifiers& flip_button1();
	key_modifiers& flip_button2();
	key_modifiers& flip_button3();
	key_modifiers& flip_button4();
	key_modifiers& flip_button5();
	key_modifiers& flip_release();

	bool any() const;
	bool none() const;
	bool shift() const;
	bool lock() const;
	bool control() const;
	bool mod1() const;
	bool mod2() const;
	bool mod3() const;
	bool mod4() const;
	bool mod5() const;
	bool button1() const;
	bool button2() const;
	bool button3() const;
	bool button4() const;
	bool button5() const;
	bool release() const;

	bool operator==(const key_modifiers& RHS) const;
	bool operator!=(const key_modifiers& RHS) const;
	
	key_modifiers& operator&=(const key_modifiers& RHS);
	key_modifiers& operator|=(const key_modifiers& RHS);

	friend const key_modifiers operator&(const key_modifiers& LHS, const key_modifiers& RHS);
	friend const key_modifiers operator|(const key_modifiers& LHS, const key_modifiers& RHS);

	friend std::ostream& operator<<(std::ostream& Stream, const k3d::key_modifiers& RHS);
	friend std::istream& operator>>(std::istream& Stream, k3d::key_modifiers& RHS);

private:
	std::bitset<14> m_storage;
};

/// High-level wrapper for keyboard functionality (bypasses the normal GTK+ event mechanism)
class ikeyboard
{
public:
	/// Defines a signal emitted whenever a key is pressed - observers should return "true" if they "consume" the event, false otherwise
	typedef unsigned int key_value_t;
	typedef SigC::Signal3<bool, icommand_node&, key_modifiers, key_value_t, k3d::marshaller::consumable> event_signal_t;
	virtual event_signal_t& event_signal() = 0;

protected:
	ikeyboard() {}
	ikeyboard(const ikeyboard&) {}
	ikeyboard& operator=(const ikeyboard&) { return *this; }
	virtual ~ikeyboard() {}
};

/// Provides singleton access to the global keyboard object
ikeyboard& keyboard();

} // namespace k3d

#endif // !K3DSDK_KEYBOARD_H
