#ifndef ROTARYENCODER_h
#define ROTARYENCODER_h

/**
 * [void description]
 * @param _cb [description]
 */
class RotaryEncoder
{

	// Private members:

	int _pinA;
	int _pinB;
	int _id;

	volatile int _state[2];
	volatile int _position;

	volatile bool _inputFlag = false;
	bool _changeFlag = false;

	unsigned long _previousTimer;
	int _interval = 200;

	void (*_cb)(RotaryEncoder*, uint8_t, int); // Callback function

	 // {newPin2, newPin1, oldPin2, oldPin1}
	int movements[5][4][4] = {
		{ // No movement
			{0, 0, 0, 0},
			{0, 1, 0, 1},
			{1, 0, 1, 0},
			{1, 1, 1, 1}
		},
		{ // +1
			{0, 0, 0, 1},
			{0, 1, 1, 1},
			{1, 0, 0, 0},
			{1, 1, 1, 0}
		},
		{ // -1
			{0, 0, 1, 0},
			{0, 1, 0, 0},
			{1, 0, 1, 1},
			{1, 1, 0, 1}
		},
		{ // +2
			{0, 0, 1, 1},
			{1, 1, 0, 0}
		},
		{ // -2
			{0, 1, 1, 0},
			{1, 0, 0, 1}
		},
	};

	// Private Functions:
	/**
	   @brief What does this do?
	 */
	void _setState(int a, int b);
	/**
	   @brief What does this do?
	 */
	void _incrementPosition(int delta);
	/**
	   @brief What does this do?
	 */
	int _findChange(int state1[2], volatile int state2[2]);
	/**
	   @brief What does this do?
	 */
	boolean _compareArrays(int a[4], int b[4]);

public:

	// Public members:

	static const uint8_t kEventStableUpdate = 0;
	static const uint8_t kEventUnstableUpdate = 1;

	//Public Functions:

	RotaryEncoder(int pinA, int pinB, int id = 99);

	/**
	   @brief What does this do?
	 */
	void initInterrupts(void (*function)());
	/**
	   @brief What does this do?
	 */
	void setEventHandler(void (*function)(RotaryEncoder*, uint8_t, int));
	/**
	   @brief What does this do?
	 */
	int getPostition();
	/**
	   @brief What does this do?
	 */
	int getId();
	/**
	   @brief What does this do?
	 */
	void setPosition(int value);
	/**
	   @brief What does this do?
	 */
	void check();

	void ICACHE_RAM_ATTR tick();

};

#endif