package de.ugoe.cs.autoquest.tasktrees.manager;

import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;

import de.ugoe.cs.autoquest.eventcore.Event;
import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTask;
import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequence;
import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTree;
import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeBuilder;
import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeNodeFactory;
import de.ugoe.cs.util.console.Console;

/**
 * TODO comment
 * 
 * @version $Revision: $ $Date: $
 * @author 2011, last modified by $Author: $
 */
public class TaskTreeManager {
    
    /** */
    private ITaskTreeBuilder taskTreeBuilder = ComponentManager.getDefaultTaskTreeBuilder();

    /** */
    private ITaskTreeNodeFactory taskTreeNodeFactory =
        ComponentManager.getDefaultTaskTreeNodeFactory();

    /** */
    private List<List<IEventTask>> sessions = null;

    /** */
    private List<IEventTask> currentSession = null;

    /**
     *
     */
    public TaskTreeManager() {
        sessions = new LinkedList<List<IEventTask>>();
    }

    /**
     *
     */
    public synchronized ITaskTree createTaskTree(Collection<List<Event>> newSessions) {
        if ((currentSession != null) || (sessions.size() > 0)) {
            throw new IllegalStateException("do not mix calls to this method with calls to the " +
                                            "other methods for handling tasks. Use only one " +
                                            "variant instead.");
        }
        
        for (List<Event> newSession : newSessions) {
            if (newSession.size() > 0) {
                for (Event event : newSession) {
                    handleNewEvent(event);
                }
                finishSession();
            }
        }
        
        return getTaskTree();
    }

    /**
     *
     */
    public void handleNewEvent(Event event) {
        assertSessionSequence();
        currentSession.add
            (taskTreeNodeFactory.createNewEventTask(event.getType(), event.getTarget()));
    }

    /**
     * 
     */
    public void finishSession() {
        if ((currentSession != null) && (currentSession.size() > 0)) {
            sessions.add(currentSession);
            currentSession = null;
        }
    }

    /**
     *
     */
    public synchronized ITaskTree getTaskTree() {
        finishSession();
        
        Console.traceln(Level.INFO, "applying temporal relationship generation rules");
        
        ISequence rootSequence = taskTreeNodeFactory.createNewSequence();
        taskTreeBuilder.setDescription(rootSequence, "root");
        
        for (List<IEventTask> session : sessions) {
            ISequence sequence = taskTreeNodeFactory.createNewSequence();
            taskTreeBuilder.setDescription(sequence, "session");
            
            for (IEventTask eventTask : session) {
                taskTreeBuilder.addChild(sequence, eventTask);
            }
            
            taskTreeBuilder.addChild(rootSequence, sequence);
        }
        
        
        ComponentManager.getTemporalRelationshipRuleManager().applyRules(rootSequence);

        return taskTreeNodeFactory.createTaskTree(rootSequence);
    }

    /**
     *
     */
    private void assertSessionSequence() {
        if (currentSession == null) {
            currentSession = new LinkedList<IEventTask>();
        }
    }

}
