#ifndef __CONTINUATION_H__
#define __CONTINUATION_H__

class Continuation
{
	public:
		// Construct a new Continuation that will start from the beginning
		// of its Run() function.
		Continuation() : _cnLine(0) { }

		// Restart Continuation.
		void Restart() { _cnLine = 0; }

		// Stop the Continuation from running. Happens automatically at END.

		void Stop() { _cnLine = LineNumberInvalid; }

		// Return true if the Continuation is running or waiting, false if it has
		// ended or exited.

		bool IsRunning() { return _cnLine != LineNumberInvalid; }

		// Run next part of Continuation or return immediately if it's still
		// waiting. Return true if Continuation is still running, false if it
		// has finished. Implement this method in your Continuation subclass.

		virtual bool Run(bool flashBlue) = 0;

		// virtual bool Run(void) = 0;

	protected:
		// Used to store a Continuation's position
		typedef unsigned short LineNumber;

		// An invalid line number, used to mark the Continuation has ended.
		static const LineNumber LineNumberInvalid = (LineNumber)(-1);

		// Stores the Continuation's position (by storing the line number of
		// the last WAIT, which is then switched on at the next Run).
		LineNumber _cnLine;
};

// Declare start of Continuation (use at start of Run() implementation).
#define BEGIN() bool _cnYielded = true; switch (_cnLine) { case 0:

// Stop Continuation and end it (use at end of Run() implementation).
#define END() default: ; } Stop(); return false;

// Cause Continuation to wait until given condition is true.
#define WAIT_UNTIL(condition) \
    do { _cnLine = __LINE__; case __LINE__: \
    if (!(condition)) return true; } while (0)

// Cause Continuation to wait while given condition is true.
#define WAIT_WHILE(condition) WAIT_UNTIL(!(condition))

// Cause Continuation to wait until given child Continuation completes.
#define WAIT_THREAD(child) WAIT_WHILE((child).Run())

// Restart and spawn given child Continuation and wait until it completes.
#define SPAWN(child) \
    do { (child).Restart(); WAIT_THREAD(child); } while (0)

// Restart Continuation's execution at its BEGIN.
#define RESTART() do { Restart(); return true; } while (0)

// Stop and exit from Continuation.
#define EXIT() do { Stop(); return false; } while (0)

// Yield Continuation till next call to its Run().
#define YIELD() \
    do { _cnYielded = false; _cnLine = __LINE__; case __LINE__: \
    if (!_cnYielded) return true; } while (0)

// Yield Continuation until given condition is true.
#define YIELD_UNTIL(condition) \
    do { _cnYielded = false; _cnLine = __LINE__; case __LINE__: \
    if (!_cnYielded || !(condition)) return true; } while (0)

#endif // __Continuation_H__
