module gedo.system.task;



public class Task
{
public:
	void stop()
	{
		if(_parent)
		{
			_parent.remove(this);
		}
	}


	void add(Task child)
	{
		assert(!child._brother);

		if(!_child)
		{
			_child = child;
		}
		else
		{
			foreach(c; this)
			{
				if(!c._brother)
				{
					c._brother = child;
					break;
				}
			}
		}

		child._parent = this;
	}


	void remove(Task child)
	{
		if(child is _child)
		{
			_child = child._brother;
		}
		else
		{
			foreach(c; this)
			{
				if(child is c._brother)
				{
					c._brother = child._brother;
					break;
				}
			}
		}

		foreach(gc; child)
		{
			child.remove(gc);
		}

		child._child   = null;
		child._parent  = null;
		child._brother = null;
	}


	int opApply(int delegate(ref Task) dg)
	{
		int result = 0;

		Task nextTask;
		for(auto child = _child; child !is null; child = nextTask)
		{
			nextTask = child._brother;

			result = dg(child);
			if(result)
			{
				break;
			}
		}

		return result;
	}


	void scanBottomUp(void delegate(Task) dg)
	{
		foreach(child; this)
		{
			child.scanBottomUp(dg);

			dg(child);
		}
	}


	void scanTopDown(void delegate(Task) dg)
	{
		foreach(child; this)
		{
			dg(child);

			child.scanTopDown(dg);
		}
	}


	Task parent()
	{
		return _parent;
	}


	Task root()
	{
		auto r = this;
		while(r.parent)
		{
			r = r.parent;
		}
		return r;
	}


	Task previous()
	{
		if(_parent)
		{
			Task p = null;
			foreach(c; _parent)
			{
				if(c is this)
				{
					break;
				}
				else
				{
					p = c;
				}
			}
			if(!p)
			{
				foreach(c; _parent)
				{
					p = c;
				}
			}

			return p;
		}
		else
		{
			return this;
		}
	}


	Task next()
	{
		if(_parent)
		{
			if(_brother)
			{
				return _brother;
			}
			else
			{
				return _parent._child;
			}
		}
		else
		{
			return this;
		}
	}


private:
	Task _parent;
	Task _child;
	Task _brother;
}



public Task findFreeTask(Task[] tasks)
{
	foreach(t; tasks)
	{
		if(!t.parent)
		{
			return t;
		}
	}

	return null;
}

