#ifndef _COMMON_VIRTUALKEY_HPP_
#define _COMMON_VIRTUALKEY_HPP_
#ifndef _COMMON_WINDOWS_HPP_
#include <common/windows.hpp>
#endif

class VirtualKey
{
public:
	enum KeyType{UpArrow=0x26,DownArrow=0x28,RightArrow=0x27,LeftArrow=0x25,
	  PageDown=0x22,PageUp=0x21,Home=0x24,End=0x23};
	VirtualKey(void);
	VirtualKey(const VirtualKey &someVirtulKey);
	VirtualKey(WORD virtualKey,LPARAM keyData=0L);
  VirtualKey(KeyType keyType,LPARAM keyData=0L);
	virtual ~VirtualKey();
	VirtualKey &operator=(const VirtualKey &someVirtualKey);
	WORD operator==(const VirtualKey &someVirtualKey);
  KeyType keyType(void)const;
	short virtualKey(void)const;
	short repeatCount(void)const;
	short scanCode(void)const;
	short isExtendedKey(void)const;
	short contextCode(void)const;
	short prevKeyState(void)const;
  short transitionState(void)const;
private:
	void virtualKey(short virtualKey);
	void repeatCount(short repeatCount);
	void scanCode(short scanCode);
	void isExtendedKey(short isExtendedKey);
	void contextCode(short contextCode);
	void prevKeyState(short prevKeyState);
	void transitionState(short transitionState);
  void setKeyData(LPARAM keyData);
	short mVirtualKey;
	short mRepeatCount;
	short mScanCode;
	short mIsExtendedKey;
	short mContextCode;
	short mPrevKeyState;
	short mTransitionState;
};

inline
VirtualKey::VirtualKey(void)
: mVirtualKey(0), mRepeatCount(0), mScanCode(0), mIsExtendedKey(FALSE), mContextCode(0),
  mPrevKeyState(0), mTransitionState(0)
{
}

inline
VirtualKey::VirtualKey(const VirtualKey &someVirtualKey)
{
  *this=someVirtualKey;
}

inline
VirtualKey::VirtualKey(WORD virtualKeyCode,LPARAM keyData)
{
	virtualKey(virtualKeyCode);
	setKeyData(keyData);
}

inline
VirtualKey::VirtualKey(KeyType keyType,LPARAM keyData)
{
	virtualKey((short)keyType);
  setKeyData(keyData);
}

inline
VirtualKey::~VirtualKey()
{
}

inline
VirtualKey &VirtualKey::operator=(const VirtualKey &someVirtualKey)
{
	virtualKey(someVirtualKey.virtualKey());
	repeatCount(someVirtualKey.repeatCount());
	scanCode(someVirtualKey.scanCode());
	isExtendedKey(someVirtualKey.isExtendedKey());
	contextCode(someVirtualKey.contextCode());
	prevKeyState(someVirtualKey.prevKeyState());
	transitionState(someVirtualKey.transitionState());
	return *this;
}

inline
WORD VirtualKey::operator==(const VirtualKey &someVirtualKey)
{
	return (virtualKey()==someVirtualKey.virtualKey()&&
					repeatCount()==someVirtualKey.repeatCount()&&
					scanCode()==someVirtualKey.scanCode()&&
					isExtendedKey()==someVirtualKey.isExtendedKey()&&
					prevKeyState()==someVirtualKey.prevKeyState()&&
          transitionState()==someVirtualKey.transitionState());
}

inline
void VirtualKey::setKeyData(LPARAM keyData)
{
	repeatCount(LOWORD(keyData));
	scanCode((keyData>>0x10)&0x80);
	isExtendedKey((keyData>>0x18)&0x01);
	contextCode((keyData>>0x1D)&0x01);
	prevKeyState((keyData>>0x1E)&0x01);
  transitionState((keyData>>0x1F)&0x01);
}

inline
VirtualKey::KeyType VirtualKey::keyType(void)const
{
	return (KeyType)mVirtualKey;
}

inline
short VirtualKey::virtualKey(void)const
{
	return mVirtualKey;
}

inline
short VirtualKey::repeatCount(void)const
{
  return mRepeatCount;
}

inline
short VirtualKey::scanCode(void)const
{
  return mScanCode;
}

inline
short VirtualKey::isExtendedKey(void)const
{
	return mIsExtendedKey;
}

inline
short VirtualKey::contextCode(void)const
{
  return mContextCode;
}

inline
short VirtualKey::prevKeyState(void)const
{
	return mPrevKeyState;
}

inline
short VirtualKey::transitionState(void)const
{
	return mTransitionState;
}

inline
void VirtualKey::virtualKey(short virtualKey)
{
	mVirtualKey=virtualKey;
}

inline
void VirtualKey::repeatCount(short repeatCount)
{
	mRepeatCount=repeatCount;
}

inline
void VirtualKey::scanCode(short scanCode)
{
	mScanCode=scanCode;
}

inline
void VirtualKey::isExtendedKey(short isExtendedKey)
{
	mIsExtendedKey=isExtendedKey;
}

inline
void VirtualKey::contextCode(short contextCode)
{
	mContextCode=contextCode;
}

inline
void VirtualKey::prevKeyState(short prevKeyState)
{
	mPrevKeyState=prevKeyState;
}

inline
void VirtualKey::transitionState(short transitionState)
{
	mTransitionState=transitionState;
}
#endif
