window.onload = function() {
  function retargetLinks () {
    var hostre = new RegExp('http://' + (location.hostname || 'nomatch'), 'i');
    var links = document.getElementsByTagName('a');
    for (var i = 0; i < links.length; i++) {
      var link = links[i];
      if (!link.target && /^http/i.test(link.href) && !hostre.test(link.href)) {
        link.target = '_blank';
      }
    }
  }

  function presoTimer() {
    var timer = joos.$('timer');
    if (!timer) {
      timer = joos.create('div', 'timer');
      timer.id = 'timer';
      document.body.appendChild(timer);
    }

    timer.innerHTML = /\d\d:\d\d:\d\d/.exec(new Date())[0];

    setTimeout(presoTimer, 1000);
  }

  function buildTOC(headingName) {
    var toc = joos.create('ol');
    toc.id = 'toc';
    var foo = new Date()*1;
    document.body.insertBefore(toc, document.body.firstChild);

    var headings = document.getElementsByTagName(headingName);

    joos.each(headings, function(el) {
      el.id = 'sect' + (foo++);
      var sect = joos.create('li', null, el.innerHTML);
      sect.heading = el;
      sect.onclick = function() {
        gotoSection(el);
        setActiveSection(el);
      };

      toc.appendChild(sect);
    });
  }

  function currentSection() {
    var h2 = activeSection();
    if (sectionVisible(h2)) return h2;

    var dist = 1e6, h2;
    var b = document.body, el = b.firstChild;
    while (el) {
      if (el.nodeName == 'H2') {
        var d = Math.abs(b.scrollTop - el.offsetTop);
        if (d < dist) {
          dist = d;
          h2 = el;
        }
      }
      el = el.nextSibling;
    }
    return h2;
  }

  function sectionVisible(h2) {
    if (!h2) return null;
    var b = document.body;
    return h2 && (h2.offsetTop >= b.scrollTop
      && h2.offsetTop < b.scrollTop + b.clientHeight);
  }

  function sectionAfter(h2) {
    h2 = h2 && h2.nextSibling;
    while (h2 && h2.nodeName != 'H2') h2 = h2.nextSibling;
    return h2;
  }

  function sectionBefore(h2) {
    h2 = h2 && h2.previousSibling;
    while (h2 && h2.nodeName != 'H2') h2 = h2.previousSibling;
    return h2;
  }

  function gotoSection(h2) {
    if (h2) slideTo(document.body, h2);
  }

  function slideTo(el, to) {
    joos.animate({
      context: el,
      to: to.offsetTop || to,
      from: el.scrollTop,
      duration: 500,
      easing: 'cos',
      onProgress: function(progress, p) {
        el.scrollTop = (p.from + progress*(p.to - p.from))|0;
      }
    });
  }

  function setActiveSection(h2) {
    var sect = null, nodes = document.body.childNodes;
    for (var i = 0; i < nodes.length; i++) {
      var node = nodes[i];
      if (node.id == 'toc') continue;
      if (node.nodeName == 'H2') sect = node;
      if (node.nodeType == 1) {
        var rawName = node.className.replace(/\s*(active|inactive)\s*/, ' ');
        if (h2) rawName += (sect == h2 ? 'active' : 'inactive');
        node.className = rawName;
      }
    }

    var toc = joos.$('toc');
    joos.each(toc.childNodes, function(el) {
      joos.toggleClass(el, 'active', el.heading == h2);
      joos.toggleClass(el, 'inactive', el.heading != h2);
      //if (el.heading == h2) slideTo(toc, el);
    });
  }

  function activeSection(h2) {
    var el = document.body.firstChild;
    while (el) {
      if (el.nodeName == 'H2' && /\bactive\b/.test(el.className)) return el;
      el = el.nextSibling;
    }
    return null;
  }

  function handleEvent(e) {
    e = e || window.event;

    var targ = e.target;

    // Ignore events in TOC and on links
    while (targ) {
      if (targ.id == 'toc' || targ.nodeName == 'A') return;
      targ = targ.parentNode;
    }

    var type = e.type;
    if (type == 'click') {
      type += '-' + e.which;
    } else if (e.charCode) {
      type += '-' + String.fromCharCode(e.charCode);
    } else if (e.keyCode) {
      switch (e.keyCode) {
        case 37: type += '-left'; break;
        case 38: type += '-up'; break;
        case 39: type += '-right'; break;
        case 40: type += '-down'; break;
      }
    }

    switch (type) {
      case 'click-1':
      case 'keypress-right':
      case 'keypress- ':
        var h2 = sectionAfter(currentSection());
        gotoSection(h2);
        setActiveSection(h2);
        e.preventDefault();
        break;

      case 'click-3':
      case 'keypress-left':
        var h2 = sectionBefore(currentSection());
        gotoSection(h2);
        setActiveSection(h2);
        e.preventDefault();
        break;

      case 'contextmenu':
        e.preventDefault();
        break;
    }
  };

  document.addEventListener('click', handleEvent, false);
  document.addEventListener('keypress', handleEvent, false);
  document.addEventListener('contextmenu', handleEvent, false);

  retargetLinks();
  buildTOC('H2');
  presoTimer();
};
