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

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

import de.ugoe.cs.quest.eventcore.Event;
import de.ugoe.cs.quest.eventcore.gui.KeyboardFocusChange;
import de.ugoe.cs.quest.tasktrees.treeifc.IEventTask;
import de.ugoe.cs.quest.tasktrees.treeifc.ISequence;
import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTree;
import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeBuilder;
import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNode;
import de.ugoe.cs.quest.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 static final int MAX_EVENTS_TILL_RULE_APPLICATION = 100;

    /** */
    private ITaskTreeBuilder taskTreeBuilder = ComponentManager.getDefaultTaskTreeBuilder();

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

    /** */
    private int eventsTillRuleApplication = MAX_EVENTS_TILL_RULE_APPLICATION;

    /** */
    private ISequence rootSequence;

    /**
     * TODO: comment
     * 
     */
    public TaskTreeManager() {
        rootSequence = taskTreeNodeFactory.createNewSequence();
    }

    /**
     * <p>
     * TODO: comment
     * </p>
     *
     * @param sequences
     * @return
     */
    public synchronized ITaskTree createTaskTree(Collection<List<Event>> sequences) {
        
        for (List<Event> sequence : sequences) {
            for (Event event : sequence) {
                handleNewEvent(event);
            }
        }
        
        return getTaskTree();
    }

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

    /**
     *
     */
    public synchronized ITaskTree getTaskTree() {
        Console.traceln(Level.INFO, "applying temporal relationship generation rules");

        ISequence currentRootSequence = rootSequence.clone();
        ComponentManager.getTemporalRelationshipRuleManager().applyRules
          (currentRootSequence, taskTreeBuilder, taskTreeNodeFactory, true);

        return taskTreeNodeFactory.createTaskTree(currentRootSequence);
    }

    /**
     * adds the task to the current or the new sequence. The decision depends on the type of task.
     * If the task finishes the current sequence, the sequence is marked as finished If the task
     * does not start a new sequence, it is added to the current sequence, before it is marked s
     * finished. Otherwise it is added to a new sequence.
     */
    private synchronized void handleEventTask(IEventTask eventTask) {
        if (!(eventTask.getEventType() instanceof KeyboardFocusChange)) {
            Console.traceln(Level.INFO, "handling interaction event task \"" + eventTask + "\"");
            addTaskToSequence(eventTask);
        }
    }

    /**
     *
     */
    private void addTaskToSequence(ITaskTreeNode task)
    {
        taskTreeBuilder.addChild(rootSequence, task);

        if (--eventsTillRuleApplication == 0) {
            eventsTillRuleApplication = MAX_EVENTS_TILL_RULE_APPLICATION;

            Console.traceln(Level.INFO, "applying temporal relationship generation rules");
            ComponentManager.getTemporalRelationshipRuleManager().applyRules(rootSequence,
                                                                             taskTreeBuilder,
                                                                             taskTreeNodeFactory,
                                                                             false);
        }
    }

}
