// jQuery table of contents plugin
// Created by Spencer Tipping and licensed under the MIT source code license

(function ($) {
  $.toc = {
    encodeText: function (text) {return text.toLowerCase ().replace (/["']/g, '').replace (/[^a-zA-Z0-9]/g, '-').
                                        replace (/-+/g, '-').replace (/-+$/, '').replace (/^-+/, '')}
  }

  $.fn.setupTableOfContents = function (options) {
    var options_prime = $.extend ({
      pathToContent:              '#content > div',
      pathToTitle:                'h1',
      variant:                    'section',
      defaultOptions:             {},
      defaultItemPath:            ':first',

      itemActivator:              function () {$(this).addClass ('selected')},
      itemDeactivator:            function () {$(this).removeClass ('selected')},
      contentActivator:           function () {$(this).show ()},
      contentDeactivator:         function () {$(this).hide ()},

      firstRunItemActivator:      null,
      firstRunItemDeactivator:    null,
      firstRunContentActivator:   null,
      firstRunContentDeactivator: null
    }, options)

    var id_unique_stuff = $.toc.encodeText ($.anchor.encodeURL (options_prime.defaultOptions))

    var id_for = function (item_name) {return id_unique_stuff + '-' + options_prime.variant + '-' + item_name}

    $(options_prime.pathToContent).each (function () {
      $(this).attr ('id', 'content-' + id_for ($.toc.encodeText ($(this).children (options_prime.pathToTitle).text ())));
      (options_prime.firstRunContentDeactivator || options_prime.contentDeactivator).apply (this, []);
    })

    var $i = function (encoded_item_name) {return $('#item-'    + id_for (encoded_item_name))}
    var $c = function (encoded_item_name) {return $('#content-' + id_for (encoded_item_name))}

    this.each (function () {
      var state_delta  = {}
      var encoded_item_name = $.toc.encodeText ($(this).text ())
      state_delta[options_prime.variant] = encoded_item_name
      if ($c (encoded_item_name).size ())
        $(this).wrap ('<a href="' + $.anchor.encodeURL ($.extend (state_delta, options_prime.defaultOptions)) + '"></a>').
                attr ('id', 'item-' + id_for (encoded_item_name));

      this != window && (options_prime.firstRunItemDeactivator || options_prime.itemDeactivator).apply (this, []);
    })

    var current_item_name = null

    var select_item = function (new_item_encoded_name, first_run) {
      if (current_item_name != new_item_encoded_name) {
        if (current_item_name) {
          var current_item    = $i(current_item_name).get (0)
          var current_content = $c(current_item_name).get (0)
          current_item    && (first_run && options_prime.firstRunItemDeactivator    || options_prime.itemDeactivator).apply    (current_item,    []);
          current_content && (first_run && options_prime.firstRunContentDeactivator || options_prime.contentDeactivator).apply (current_content, []);
        }

        var new_item    = $i(new_item_encoded_name).get (0)
        var new_content = $c(new_item_encoded_name).get (0)
        new_item    && (first_run && options_prime.firstRunItemActivator    || options_prime.itemActivator).apply    (new_item,    []);
        new_content && (first_run && options_prime.firstRunContentActivator || options_prime.contentActivator).apply (new_content, []);
        current_item_name = new_item_encoded_name
      }
    }

    var default_item = function () {
      return $.toc.encodeText ($(options_prime.pathToContent).filter (options_prime.defaultItemPath).children (options_prime.pathToTitle).text ())
    }

    select_item ($.anchor.state ()[options_prime.variant] || default_item (), true)

    $.anchor.listen (function () {
      select_item (this[options_prime.variant] || default_item ())
    })

    return this
  }
}) (jQuery)