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

import java.util.HashMap;
import java.util.Map;

import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTree;
import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeNode;
import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeNodeInfo;

/**
 * TODO comment
 * 
 * @version $Revision: $ $Date: 21.02.2012$
 * @author 2012, last modified by $Author: patrick$
 */
public class TaskTree implements ITaskTree {
    
    /** the map of nodes */
    private Map<ITaskTreeNode, ITaskTreeNodeInfo> taskMap;

    /** the root node of the task tree */
    private ITaskTreeNode rootNode;

    /**
     * TODO: comment
     * 
     */
    TaskTree(ITaskTreeNode rootNode) {
        this.rootNode = rootNode;
    }

    /*
     * (non-Javadoc)
     * 
     * @see de.ugoe.cs.tasktree.treeifc.TaskTree#getRoot()
     */
    @Override
    public ITaskTreeNode getRoot() {
        return rootNode;
    }

    /*
     * (non-Javadoc)
     * 
     * @see de.ugoe.cs.tasktree.treeifc.TaskTree#getTaskMap()
     */
    @Override
    public synchronized Map<ITaskTreeNode, ITaskTreeNodeInfo> getTaskMap() {
        if (taskMap == null) {
            taskMap = new HashMap<ITaskTreeNode, ITaskTreeNodeInfo>();
            addNodeToMap(rootNode, null);
        }
        return taskMap;
    }

    /**
     * TODO: comment
     * 
     * @param rootNode
     */
    private void addNodeToMap(ITaskTreeNode node, ITaskTreeNode parent) {
        NodeInfo nodeInfo = (NodeInfo) taskMap.get(node);

        if (nodeInfo == null) {
            nodeInfo = new NodeInfo(node);
            taskMap.put(node, nodeInfo);
        }

        if (parent != null) {
            // through first removing an existing parent it is assured, that a parent is recorded
            // only once. This is needed, because parent may be reused in a tree as well, but we
            // always iterate the whole tree
            nodeInfo.removeParent(parent);
            nodeInfo.addParent(parent);
        }

        for (ITaskTreeNode child : node.getChildren()) {
            addNodeToMap(child, node);
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.lang.Object#clone()
     */
    @Override
    public TaskTree clone() {
        TaskTree clone = null;
        try {
            clone = (TaskTree) super.clone();

            clone.rootNode = rootNode.clone();

            // the clone will create the task map itself, when it is first retrieved
            clone.taskMap = null;

        }
        catch (CloneNotSupportedException e) {
            // this should never happen. Therefore simply dump the exception
            e.printStackTrace();
        }

        return clone;
    }

}
