package de.ugoe.cs.autoquest.usability.taskmodel.filter;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;

import org.apache.commons.collections15.Closure;
import org.apache.commons.collections15.CollectionUtils;

import de.ugoe.cs.autoquest.tasktrees.treeifc.IMarkingTemporalRelationship;
import de.ugoe.cs.autoquest.tasktrees.treeifc.IStructuringTemporalRelationship;
import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel;

public class BFSTaskModelIterator implements Iterator<ITask> {

	private final Queue<ITask> unvisitedTasks = new LinkedList<ITask>();

	private BFSTaskModelIterator(ITaskModel taskModel) {
		unvisitedTasks.addAll(taskModel.getTasks());
	}

	public static BFSTaskModelIterator iterator(ITaskModel taskModel) {
		return new BFSTaskModelIterator(taskModel);
	}

	@Override
	public boolean hasNext() {
		return !this.unvisitedTasks.isEmpty();
	}

	@Override
	public ITask next() {
		ITask task = unvisitedTasks.poll();
		processChildrenOfCurrentTask(task);
		return task;
	}

	private void processChildrenOfCurrentTask(ITask task) {
		if (task instanceof IStructuringTemporalRelationship) {
			CollectionUtils.forAllDo(
					((IStructuringTemporalRelationship) task).getChildren(),
					addToUnvisitedTasks());
		} else if (task instanceof IMarkingTemporalRelationship) {
			addToUnvisitedTasks().execute(
					((IMarkingTemporalRelationship) task).getMarkedTask());
		}
	}

	private Closure<ITask> addToUnvisitedTasks() {
		return new Closure<ITask>() {

			@Override
			public void execute(ITask childTask) {
				unvisitedTasks.add(childTask);
			}
		};
	}

	@Override
	public void remove() {
		// do nothing
	}

}
