/*
 * Switch.h
 *
 *  Created on: 2009-07-07
 *      Author: wasyl
 */

#ifndef SWITCH_H_
#define SWITCH_H_

#include <vector>

/**
 * Represents a single two-state input switch.
 */
class Switch
{
private:
	static std::vector<Switch *> sPrimaries;

private:
	bool mPrimary;
	std::vector<Switch *> mDependent;

protected:
	Switch(bool primary);

public:
	virtual ~Switch();

	/**
	 * Returns true if the switch is on, false otherwise.
	 */
	virtual bool on() = 0;

	/**
	 * Updates the state of the switch.
	 */
	virtual void update() = 0;

	/**
	 * Returns true if this is a primary switch (i.e keyboard key),
	 * or false if it is derived.
	 */
	bool primary() { return mPrimary; };

	/**
	 * Registers a derived switch that depends on this one.
	 */
	void registerDependent(Switch *dependent);

	/**
	 * Unregisters a derived switch.
	 */
	void unregisterDependent(Switch *dependent);

	/**
	 * Updates all the dependent switches.
	 */
	void updateDependent();

	/**
	 * Allows to use the switch in if() tests.
	 */
	operator bool() { return on(); }

	/**
	 * Updates all primary switches.
	 */
	static void updatePrimaries();
};

/****************************************************/

class OnPress : public Switch
{
private:
	Switch *mBase;
	bool mNow, mPrev;
public:
	OnPress(Switch *base) : Switch(false), mBase(base), mNow(false), mPrev(false) { mBase->registerDependent(this); };
	bool on() { return (mNow != mPrev) && (mNow); };
	void update() { mPrev = mNow; mNow = mBase->on(); updateDependent();};
};

/****************************************************/

class OnRelease : public Switch
{
private:
	Switch *mBase;
	bool mNow, mPrev;
public:
	OnRelease(Switch *base) : Switch(false), mBase(base), mNow(false), mPrev(false) { mBase->registerDependent(this); };
	bool on() { return (mNow != mPrev) && (!mNow); };
	void update() { mPrev = mNow; mNow = *mBase; updateDependent();};
};

/****************************************************/

#endif /* SWITCH_H_ */
