module y4d_input.keyinputbase;

///	入力用の基底クラス。
/**
<PRE>
	軸入力もボタンとして扱う。
		↑:0　↓:1　←:2　→:3
		1つ目のボタン:4  2つ目のボタン:5  3つ目のボタン:6..
</PRE>
*/
interface KeyInputBase {
	///	現在押されているか(状態はupdate関数を呼び出さないと更新されない)
	bool isPress(int nButtonNo);

	///	前回のupdateのときに押されていなくて、今回のupdateで押されたか
	bool isPush(int nButtonNo);

	///	前回のupdateのときに押されていなくて、今回のupdateで押されたか
	void update();
	/// update監視
	void updateMark();

	///	デバイス名の取得
	char[] getDeviceName();

	///	デバイスのボタンの数
	int getButtonNum();

	///	デバイスの固有情報を返す
	/**
			JoyStickならば、SDL_Joystick*
				(SDLのJoyStickのAPIを直接呼びたいときに)
			KeyInputNullDeviceならばならば、null
	*/
	void* getInfo();
}

///	入力系のnull device。
/**
	KeyInputBaseで、すべての関数が何もしないように実装されたクラス。
	JoyStickがつながっていないときなど、内部的には、このクラスをnewして、
	そのオブジェクトに委譲してやればnullチェックが省略できる、というもの。
*/
class KeyInputNullDevice : KeyInputBase {
	bool isPush(int nButtonNo) { return false; }
	bool isPress(int nButtonNo) { return false; }
	void update() { }
	void updateMark() { }
	char[] getDeviceName() { return cast(char[]) "KeyInputNullDevice"; }
	int getButtonNum() { return 0; }
	void* getInfo() { return null; }
	
	/// インスタンスを生成する
	static KeyInputNullDevice getInstance() {
		if (obj is null) {
			obj = new KeyInputNullDevice();
		}
		return obj;
	}
	
private:
	static KeyInputNullDevice obj = null;
	this() {
	}
}

/**
*/
class NullableKeyInput : KeyInputBase {
	bool isPush(int nButtonNo) { return get().isPush(nButtonNo); }
	bool isPress(int nButtonNo) { return get().isPress(nButtonNo); }
	void update() { get().update(); }
	void updateMark() { get().updateMark(); }
	char[] getDeviceName() { return get().getDeviceName(); }
	int getButtonNum() { return get().getButtonNum(); }
	void* getInfo() { return get().getInfo(); }

	/// ヌルデバイスに切り替える
	void disable() {
		this.enableDevice = false;
	}
	/// ノーマルデバイスに切り替える
	void enable() {
		this.enableDevice = true;
	}
	/// デバイスが有効になっているか？
	bool isEnable() {
		return this.enableDevice;
	}
	/// オリジナルのデバイスを取得する
	KeyInputBase getOriginal() {
		return this.key;
	}
	/// コンストラクタ
	this(KeyInputBase key_) {
		this.key = key_;
		this.enableDevice = true;
	}
	/// 静的コンストラクタ
	static this() {
		nullKey = new KeyInputNullDevice();
	}
	
private:
	KeyInputBase get() {
		return enableDevice ? this.key : nullKey;
	}

	static KeyInputBase nullKey;
	KeyInputBase key;
	bool enableDevice;
}
