
var prefixDelimiter = "-";
var nodePathPrefix = "section" + prefixDelimiter;
var linkIDPrefix = "link" + prefixDelimiter;
var sectionIDPrefix = "";
var nodeDelimiter = ".";

var nodeDelimiterPattern = new RegExp("[" + nodeDelimiter + "]");
var previousSelectedNodePathString = null;
var pathPattern = new RegExp("^([^0-9]+[" + prefixDelimiter + "])?((?:0|[1-9][0-9]*)(?:[" + nodeDelimiter + "](?:0|[1-9][0-9]*))*)$");
function select (selectedNodePathString, clickedLink)
{
  if (clickedLink == null) {
    if (selectedNodePathString == previousSelectedNodePathString) {
      return false;
    }
  }
  previousSelectedNodePathString = selectedNodePathString;
  // alert ("'" + selectedNodePathString + "', " + (clickedLink != null ? "link" : "null"));
  if (clickedLink != null) clickedLink.blur ();
  if (! document.getElementById) return true;
  var linkToSection;
  if (clickedLink != null) {
    linkToSection = clickedLink;
  } else {
    linkToSection = document.getElementById(linkIDPrefix + selectedNodePathString);
  }
  if (linkToSection == null) return true;
  var linkedDoc = partBefore('.html', partBefore('#', linkToSection.href));
  var thisDoc = partBefore('.html', partBefore('#', window.location.href));
  if (linkedDoc != thisDoc) {
    if (clickedLink == null) return true;
    if (! navigator.cookieEnabled) return true;
    setSessionCookie("selection", selectedNodePathString);
    window.location = linkedDoc;
    return false;
  }
  var matchResult = pathPattern.exec(selectedNodePathString);
  if (matchResult != null) {
    var prefix = matchResult[1];
    var selectedNodePath = matchResult[2].split(nodeDelimiterPattern);
    // var log = "";
    // log +=
    setActivities(linkIDPrefix + prefix, true, selectedNodePath, 0);
    // log +=
    setActivities(sectionIDPrefix + prefix, false, selectedNodePath, 0);
    window.scrollTo(0, 0);
    // alert(log);
    return false;
  } else {
    return true;
  }
}

function setActivities (idPrefix, treeView, selectedNodePath, pathLevel)
{
  // var log = "";
  var selectedNodeOnLevel = selectedNodePath != null && pathLevel < selectedNodePath.length ? selectedNodePath[pathLevel] : null;
  var nodeOnLevel = 0;
  while (true) {
    var nextId = idPrefix + nodeOnLevel;
    var onPath = selectedNodePath != null && nodeOnLevel == selectedNodeOnLevel;
    var element = document.getElementById(nextId);
    if (element != null) {
      var activity = onPath ? pathLevel == selectedNodePath.length - 1 ? 3.1 : 2.2 : selectedNodePath != null ? treeView ? 1.3 : pathLevel == selectedNodePath.length && nodeOnLevel == 0 ? 1.4 : 0.5 : 0.6;
      // log += nextId + " > " + activity + "\n";
      setActivity(element, Math.floor(activity));
      if (treeView) {
          setActivity(element.parentNode, Math.floor(activity));
      }
      // log +=
      setActivities(nextId + nodeDelimiter, treeView, onPath ? selectedNodePath : null, pathLevel + 1);
      nodeOnLevel += 1;
    } else if (nodeOnLevel == 0) {
      nodeOnLevel += 1;
    } else if (selectedNodeOnLevel != null && nodeOnLevel < selectedNodeOnLevel) {
      nodeOnLevel = selectedNodeOnLevel;
    } else {
      if (onPath) {
        // log +=
        setActivities(nextId + nodeDelimiter, treeView, selectedNodePath, pathLevel + 1);
      }
      break;
    }
  }
  // return log;
}

var activityPattern = new RegExp("(^|^.* )(active([0-9]))( .*$|$)");
function setActivity (element, activityLevel)
{
  var newLevel = "active" + activityLevel;
  var matchResult = activityPattern.exec(element.className);
  if (matchResult == null) {
    if (element.className == null) {
      element.className = newLevel;
    } else {
      element.className += " " + newLevel;
    }
  } else {
    element.className = matchResult[1] + newLevel + matchResult[4];
  }
}

function getActivity (element)
{
  var matchResult = activityPattern.exec(element.className);
  return matchResult && matchResult[3];
}

function replaceLastClassName (element, newClassName)
{
  var pos = element.className.lastIndexOf(" ");
  element.className = element.className.substring(0, pos+1) + newClassName;
}

function dumpObject (object, objectName, level)
{
  var result = "";
  if (typeof(object) == "object" && level-- != 0) {
    for (var memberName in object)
    {
      var member = object[memberName];
      result += dumpObject(typeof(member) == "function" ? "function" : member, objectName + "." + memberName, level);
    }
  } else {
    result += objectName + ": " + object + "\r\n";
  }
  return result;
}

function linkClicked (link)
{
  var selection;
  if ((selection = afterInitial(linkIDPrefix, link.id)) != null) {
    // alert('ID: ' + selection);
    return select(selection, link);
  }
  var url = link.href;
  var hashPos = url.indexOf('#');
  if (hashPos >= 0 && hashPos < url.length - 1) {
    selection = partAfter(sectionIDPrefix, url.substring(hashPos + 1));
    // alert('target: ' + selection);
    return select(selection, link);
  }
  return true;
}

function selectOnLoad (defaultSelection)
{
  var url = window.location.href, selection;
  var hashPos = url.indexOf('#');
  if (hashPos >= 0 && hashPos < url.length - 1) {
    selection = partAfter(sectionIDPrefix, url.substring(hashPos + 1));
    if (! navigator.cookieEnabled) {
      // alert("hash without cookie: " + selection);
      window.location.replace(url.substring(0, hashPos + 1));
    } else {
      setSessionCookie("selection", selection);
      // alert("hash and cookie: " + selection);
      window.location.replace(url.substring(0, hashPos));
      /* because the URL we reload to does not contain the trailing hash, some browsers (IE) will trigger a new onLoad after this function returns, some won't (Mozilla) */
    }
  } else if ((selection = getSessionCookie("selection")) != null) {
    deleteSessionCookie("selection");
    // alert("cookie: " + selection);
  } else if (typeof SearchHighlighter == "function") {
    var highlighter = new SearchHighlighter();
    highlighter.setSearchRoot("content");
    highlighter.setCallback(selectSearchResult);
    if (highlighter.getEngineSearchPhrase()) {
      setActivities(linkIDPrefix + nodePathPrefix, true, [ ], 0);
      setActivities(sectionIDPrefix + nodePathPrefix, false, [ ], 0);
      highlighter.highlight();
      window.scroll(0, 0);
      // setSessionCookie(defaultSelection);
      return true;
    } else {
      selection = defaultSelection;
    }
    // alert("default: " + selection);
  } else {
    selection = defaultSelection;
  }
  if (previousSelectedNodePathString == null) {
    if (select(selection) && selection != defaultSelection) {
      select(defaultSelection);
    }
  }
  // setTimeout("selectFromURLor('" + defaultSelection + "');", 200);
  return true;
}

function selectSearchResult (element)
{
  var parent = element, matchResult = null;
  do {
    if ((matchResult = pathPattern.exec(parent.id))) {
      break;
    }
    parent = parent.parentNode;
  } while (parent && parent.id != "content");
  if (!matchResult) {
    return;
  }
  var selectedNodePath = matchResult[2], activity = 2;
  do {
    increaseActivityById(linkIDPrefix + nodePathPrefix + selectedNodePath, activity);
    increaseActivityById(sectionIDPrefix + nodePathPrefix + selectedNodePath, activity);
    var pos = selectedNodePath.lastIndexOf(nodeDelimiter);
    if (activity > 1 && selectedNodePath.substring(pos + 1) != "0") {
      activity = 1;
    }
    selectedNodePath = selectedNodePath.substring(0, pos);
  } while (selectedNodePath);
}

function increaseActivityById (id, activity)
{
  var element;
  if ((element = document.getElementById(id))) {
    var oldActivity = getActivity(element);
    // alert(id + ", " + oldActivity + ", " + activity);
    if ((!oldActivity) || oldActivity - 0 < activity) {
      setActivity(element, activity);
    }
  }
}

function setSessionCookie (name, value)
{
  document.cookie = name + "==" + escape (value);
}

function getSessionCookie (name)
{
  var arg = name + "==";
  var alen = arg.length;
  var clen = document.cookie.length;
  var i = 0;
  while (i < clen) {
    var j = i + alen;
    if (document.cookie.substring(i, j) == arg) {
      var endPos = document.cookie.indexOf (";", j);
      if (endPos < 0) endPos = document.cookie.length;
      return unescape(document.cookie.substring(j, endPos));
    }
    i = document.cookie.indexOf(" ", i) + 1;
    if (i == 0) break;
  }
  return null;
} 

function deleteSessionCookie (name) {
  // if (getSessionCookie(name)) {
  document.cookie = name + "="; // + "; expires=Thu, 01-Jan-70 00:00:01 GMT";
  // }
}

function partBefore (delimiter, string)
{
  var pos = string.indexOf(delimiter);
  return pos < 0 ? string : string.substring(0, pos);
}

function partAfter (delimiter, string)
{
  var pos = string.indexOf(delimiter);
  return pos < 0 ? string : string.substring(pos + delimiter.length);
}

function afterInitial (initial, string)
{
  if (string != null && initial != null && string.substring(0, initial.length) == initial) {
    return string.substring(initial.length);
  } else {
    return null;
  }
}

function skipNavigation (link)
{
  var id = partAfter("#", link.hash);
  var target = document.getElementById(id);
  if (target != null) {
    if (!(target.tagName.toLowerCase() in { a: true, select: true, input: true, textarea: true })) {
      if (!target.focusLink) {
        var focusLink = document.createElement("a");
        focusLink.setAttribute("href", "");
        focusLink.setAttribute("onClick", "return false;");
        target.insertBefore(focusLink, target.firstChild);
        target.focusLink = focusLink;
      }
      target = target.focusLink;
    }
    scrollToTop(target);
    target.focus();
    setTimeout(function () { target.blur(); }, 1);
    return false;
  }
  return true;
}

function scrollToTop (element)
{
  var scrollTop = 0;
  while (element.offsetParent) {
    scrollTop += element.offsetTop;
    element = element.offsetParent;
  }
  window.scroll(0, scrollTop);
}
