
package de.ugoe.cs.autoquest.plugin.usability2.tools;

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTask;
import de.ugoe.cs.autoquest.tasktrees.treeifc.IIteration;
import de.ugoe.cs.autoquest.tasktrees.treeifc.IOptional;
import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelection;
import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequence;
import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskVisitor;

public class TaskUtilities {

    static class RootTaskFilterVisitor implements ITaskVisitor {
        final Set<ITask> nonRootTasks;
        private boolean first ;

        public RootTaskFilterVisitor(Set<ITask> nonRootTasks) {
            this.nonRootTasks = nonRootTasks;
        }
        
        private boolean filter(ITask task) {
            boolean result = true;
            
            if(!first)
                result = nonRootTasks.add(task);
            else
                first = false;
            return result;
        }
        
        @Override
        public void visit(IEventTask eventTask) {
            filter(eventTask);
        }

        @Override
        public void visit(IIteration iteration) {
            iteration.getMarkedTask().accept(this);
        }

        @Override
        public void visit(IOptional optional) {
            optional.getMarkedTask().accept(this);
        }

        @Override
        public void visit(ISelection selection) {
            for (ITask child : selection.getChildren()) {
                child.accept(this);
            }
        }

        @Override
        public void visit(ISequence sequence) {
            for (ITask child : sequence.getChildren()) {
                child.accept(this);
            }
        }

        @Override
        public void visit(ITask task) {
            boolean unknown = filter(task);

            if (unknown /* or first==True */) {
                if (task instanceof IEventTask) {
                    visit((IEventTask) task);
                }
                else if (task instanceof IIteration) {
                    visit((IIteration) task);
                }
                else if (task instanceof IOptional) {
                    visit((IOptional) task);
                }
                else if (task instanceof ISelection) {
                    visit((ISelection) task);
                }
                else if (task instanceof ISequence) {
                    visit((ISequence) task);
                }
            }
        }

        public void reset() {
            this.first =true;
        }
    }

    public static Collection<ITask> findRootTasks(Collection<ITask> tasks) {
        Set<ITask> rootTasks = new HashSet<ITask>(tasks);
        Set<ITask> nonRootTasks = new HashSet<ITask>();
        RootTaskFilterVisitor visitor = new RootTaskFilterVisitor(nonRootTasks);
        
        for (ITask iTask : tasks) {
            if(!nonRootTasks.contains(iTask)) {
                visitor.reset();
                iTask.accept(visitor);
            }
        }
        
        rootTasks.removeAll(nonRootTasks);
        System.out.printf("Reduced tasks from %d to %d\n", tasks.size(), rootTasks.size());
        
        return rootTasks;
    }

}
