namespace PF {
	/** Queue of paths to be processed by the system */
	class ThreadControlQueue 
	{

		Path head;
		Path tail;
		/** Create a new queue with the specified number of receivers.
		 * It is important that the number of receivers is fixed.
		 * Properties like AllReceiversBlocked rely on knowing the exact number of receivers using the Pop (or PopNoBlock) methods.
		 */
		public ThreadControlQueue (int numReceivers) {
		}

		/** True if the queue is empty */
		public bool IsEmpty {
			get {
				return head == null;
			}
		}


		/** Push a path to the front of the queue */
		public void PushFront (Path path) {
				if (tail == null) {// (tail == null) ==> (head == null)
					head = path;
					tail = path;
				} else {
					path.next = head;
					head = path;
				}
		}

		/** Push a path to the end of the queue */
		public void Push (Path path) {
			if (tail == null) {// (tail == null) ==> (head == null)
				head = path;
				tail = path;
			} else {
				tail.next = path;
				tail = path;
			}
		}

		/** Pops the next item off the queue.
		 * This call will block if there are no items in the queue or if the queue is currently blocked.
		 *
		 * \returns A Path object, guaranteed to be not null.
		 * \throws QueueTerminationException if #TerminateReceivers has been called.
		 * \throws System.InvalidOperationException if more receivers get blocked than the fixed count sent to the constructor
		 */
		public Path Pop () 
		{
			if (this.head == null)
			{
				return null;
			}
			Path p = head;

			var newHead = head.next;
			if (newHead == null) 
			{
				tail = null;
			}
			head.next = null;
			head = newHead;
			return p;
		}

		/** Pops the next item off the queue, this call will not block.
		 * To ensure stability, the caller must follow this pattern.
		 * 1. Call PopNoBlock(false), if a null value is returned, wait for a bit (e.g yield return null in a Unity coroutine)
		 * 2. try again with PopNoBlock(true), if still null, wait for a bit
		 * 3. Repeat from step 2.
		 *
		 * \throws QueueTerminationException if #TerminateReceivers has been called.
		 * \throws System.InvalidOperationException if more receivers get blocked than the fixed count sent to the constructor
		 */
		public Path PopNoBlock (bool blockedBefore) 
		{
			if (this.head == null)
			{
				return null;
			}
			Path p = head;

			var newHead = head.next;
			if (newHead == null) {
				tail = null;
			}
			head.next = null;
			head = newHead;
			return p;
		}
	}
}
