// loads tree from given node array
// array must be well ordered (all parents preceding its children)
function loadTree(nodes, contID) {
  var cont = document.getElementById(contID);
  
  // create treebox and nodebox for all root nodes
  var i = 1;
  var nb;
  var treeRoot;

  for (idx in nodes) {
    if (nodes[idx] == null) continue;
    if (nodes[idx].parentID != '-1') continue;
    if (typeof(nodes[idx]) == 'function') continue;
  
    // tree box
    treeRoot = document.createElement("div");
    treeRoot.className = "treebox treeroot";
    cont.appendChild(treeRoot);

    // node box  
    nb = createNodeBox(nodes[idx]);
    treeRoot.appendChild(nb);
  }

  var parent;
  var tb;

  for (idx in nodes) {
    if (nodes[idx] == null) continue;
    if (nodes[idx].parentID == '-1') continue;
    if (typeof(nodes[idx]) == 'function') continue;

    // get parent
    parent = document.getElementById("node_" + nodes[idx].parentID);

    // create nodebox in treebox
    nb = createNodeBox(nodes[idx]);
    tb = createTreeBox();

    tb.appendChild(nb);
    parent.parentNode.appendChild(tb);
  }
  
  // close all closed nodes
  for (idx in nodes) {
    if (nodes[idx] == null) continue;
    if (typeof(nodes[idx]) == 'function') continue;
    if (!nodes[idx].opened) {
      nodes[idx].opened = true;
      nodeOpen(document.getElementById('nodespan_' + nodes[idx].nodeID), nodes);
    }
  }
}

// creates empty tree box
function createTreeBox() {
  var newDiv = document.createElement("div");
  newDiv.className = "treebox";
  
  return newDiv;
}

// creates node box for specified node
function createNodeBox(node) {
  var newDiv = document.createElement("div");
  newDiv.className = "nodebox";
  newDiv.id = "node_" + node.nodeID;
  newDiv.name = node.nodeID;
  newDiv.innerHTML = "<p><span class=\"opener isopen\" id=\"nodespan_" + node.nodeID + "\" onclick=\"nodeOpen(this, maNodes)\">&nbsp;</span>" +
  						"<span id=\"rtn_" + node.nodeID + "\" class=\"type_" + node.type + node.stateText + 
                                 (node.type == 'activity' && node.afterDDT ? ' afterddt' : '') + "\" " +
                               "onclick=\"nodeClickEvent(this, '" + node.nodeID + "')\">" + node.text +
                        "</span>" +
                        "<br/><span id=\"masfx_" + node.nodeID + "\" class=\"suffix\">" + node.suffix + "</span>" +
                        "</p>";
  
  return newDiv;
}

// updates node class
function updateNodeClass(nodeObj) {
  var span = document.getElementById('rtn_' + nodeObj.nodeID);
  span.className = 'type_' + nodeObj.type + nodeObj.stateText;
}

// opens or closes node
function nodeOpen(node, nodes) {
  // get node id
  var nodeID = node.id.substring(9);

  // get nodebox parent (its tree box)
  var box = document.getElementById("node_" + nodeID).parentNode;
  
  // switch property
  var display = '';
  if (nodes[nodeID].opened) display = 'none';
  nodes[nodeID].opened = !nodes[nodeID].opened;
  if (box.childNodes.length == 1) nodes[nodeID].opened = true;

  // set new icon
  if (nodes[nodeID].opened) node.className = node.className.replace('isclose', 'isopen');
  else node.className = node.className.replace('isopen', 'isclose');       
  
  // show / hide all tree boxes of given node box
  for (var i = 0; i < box.childNodes.length; i ++)
    if (box.childNodes[i].className != 'nodebox') box.childNodes[i].style.display = display;
}

// moves one node
function maMoveTreeNode(nodeObj, isUp) {
  var parent = document.getElementById('node_' + maNodes[nodeObj.parentID].nodeID).parentNode;

  var idx = 0;
  var nodePos = -1;
  var nodeCnt = 0;
  var nodeIdx = new Array();
  for (idx = 0; idx < parent.childNodes.length; idx++)
    if (parent.childNodes[idx].childNodes != null &&
        parent.childNodes[idx].childNodes.length > 0 &&
        parent.childNodes[idx].childNodes[0].tagName == 'DIV') {
          if (parent.childNodes[idx].childNodes[0].name == nodeObj.nodeID) nodePos = nodeCnt;
          nodeIdx[nodeCnt++] = idx;
        }

  var transition = isUp ? -1 : +1;
  if (nodePos == -1 || nodePos + transition < 0 || nodePos + transition >= nodeCnt) return;

  if (isUp) {
    var hlpNode = parent.childNodes[nodeIdx[nodePos]];
    parent.removeChild(parent.childNodes[nodeIdx[nodePos]]);
    parent.insertBefore(hlpNode, parent.childNodes[nodeIdx[nodePos + transition]]);
  } else {
    var hlpNode = parent.childNodes[nodeIdx[nodePos + transition]];
    parent.removeChild(parent.childNodes[nodeIdx[nodePos + transition]]);
    parent.insertBefore(hlpNode, parent.childNodes[nodeIdx[nodePos]]);
  }
}

// expands full tree
function treeExpandAll() {
  for (idx in maNodes) {
    if (typeof(maNodes[idx]) == 'function') continue;
    maNodes[idx].opened = false;
    nodeOpen(document.getElementById('nodespan_' + maNodes[idx].nodeID), maNodes);
  }
}

// collapses full tree
function treeCollapseAll() {
  for (idx in maNodes) {
    if (typeof(maNodes[idx]) == 'function') continue;
    maNodes[idx].opened = true;
    nodeOpen(document.getElementById('nodespan_' + maNodes[idx].nodeID), maNodes);
  }
}

