/**
  Accordion
  
  Description:
  
  Used to manipulate the DOM of a page to create expandable content areas 
  that get expanded/contracted with configurable "triggers" and a "more" 
  link at the end of each collapsed content area.
  
  Requires:
  
    * jQuery 1.3+

  Usage:
  
      $(function(){
        // create new accordion
        var content_accordion = new Accordion("#content > h3");
        // collapse all by default
        content_accordion.collapseAll();
      });
  
  This would make the "h3" elements the "triggers" in this new accordion. 
  These triggers are made clickable to expand and collapse the content areas 
  beneath them.
  
  The DOM elements that follow each trigger, usually paragraphs or lists, 
  are grouped into separate DIVs to make them into "content areas" that 
  get toggled by their triggers.
  
  Notes on Collapsing Content Area Behavior:
  
  Each content area is searched for the number of children inside them. If 
  there is only one child, collapsing that content area will not be possible. 
  If there is more than one child, the first child will be treated as the 
  "excerpt" for that content area (so it makes sense to keep that element small) 
  and the content area will become collapsible.
  
*/
var Accordion = function(trigger_selector, options){
  var accordion = this;
  accordion.options = $.extend(accordion.options, options || {});
  
  // handle more link
  if(accordion.options.more_link === true){
    accordion.options.more_link = 'More...';
  }
  
  // append ids and classes to accordion triggers.
  $(trigger_selector).each(function(i){
    $(this).attr("id", accordion.trigger_class + '_' + (i + 1)).addClass(accordion.trigger_class);
  });
  accordion.triggers = $("."+accordion.trigger_class);
  // find content areas (the content after each trigger) and append ids and classes to the content areas.
  accordion.triggers.each(function(i){
    var trigger = this;
    trigger.cutoff_point = -1;
    trigger.excerpt_point = -1;
    var nextAll = $(this).nextAll();
    var area_nodes = nextAll.each(function(j){
      trigger.excerpt_point = 1;
      // if($(this).is(accordion.options.excerpt_separator)){
      //   trigger.excerpt_point = j;
      // }
      if(trigger.cutoff_point != -1){
        return;
      }
      if($(this).hasClass(accordion.trigger_class)){
        trigger.cutoff_point = j;
      }
      else if(j == nextAll.length - 1){
        trigger.cutoff_point = nextAll.length;
      }
    }).filter(function(i){
      return i < trigger.cutoff_point;
    }).wrapAll($('<div></div>').attr({ 'id': accordion.contentarea_class + '_' + (i + 1), 'class': accordion.contentarea_class }));
  });

  accordion.contentareas = $("."+accordion.contentarea_class);
  accordion.contentareas.each(function(){
    // extend each content area object with some custom methods.
    $.extend(this, {
      expanded: true,
      openclass: 'accordion_contentarea_open',
      closedclass: 'accordion_contentarea_closed',
      index: parseInt($(this).attr("id").split(accordion.contentarea_class + "_")[1]),
      /**
       * Return DOM element (not jQuery object) for this content area's trigger.
       */
      trigger: function(){
        return $("#" + accordion.trigger_class + "_" + this.index)[0];
      },
      markAsOpen: function(){
        var contentarea = this;
        $(this).removeClass(contentarea.closedclass).addClass(contentarea.openclass);
        contentarea.trigger().markAsOpen();
      },
      markAsClosed: function(){
        var contentarea = this;
        $(this).removeClass(contentarea.openclass).addClass(contentarea.closedclass);
        contentarea.trigger().markAsClosed();
      },
      /**
       * Collapse this content area and return its jQuery object.
       * Returns false if area is already collapsed.
       */
      collapse: function(){
        var contentarea = this;
        if(contentarea.expanded == false || $(contentarea).data('excerpt') == false || $(contentarea).children().length == 1){
          return false;
        }
        var toggle = function(e){
          e.preventDefault();
          contentarea.toggle();
        };
        contentarea.expanded = !contentarea.expanded;
        return $(contentarea).html($(contentarea).data('excerpt')).each(contentarea.markAsClosed).each(function(){
          $(".accordion_more_link", $(this)).unbind('click').bind('click', toggle);
        });
      },
      /**
       * Expand this content area and return its jQuery object.
       * Returns false if area is already expanded.
       */
      expand: function(){
        var contentarea = this;
        if(contentarea.expanded == true){
          return false;
        }
        contentarea.expanded = !contentarea.expanded;
        return $(contentarea).html($(contentarea).data('full')).each(contentarea.markAsOpen);
      },
      /**
       * Expand or Collapse this content area and return its jQuery object.
       */
      toggle: function(){
        var contentarea = this;
        if(contentarea.expanded){
          return contentarea.collapse();
        }
        return contentarea.expand();
      }
    });

    // attach excerpt and full text data
    var excerpt = false; // $('<p></p>').append($(this).text().substring(0, accordion.chars_to_show) + '...');
    if(this.trigger().excerpt_point > -1){
      excerpt = $(this).children().slice(0, this.trigger().excerpt_point);
      // $(this).children().eq(this.trigger().excerpt_point).is(accordion.options.excerpt_separator).remove(); // remove the "hr"
      if(accordion.options.more_link){
        $.each([
          ' ',
          $("<a></a>").attr({ 'class': 'accordion_more_link', href: '#' }).text(accordion.options.more_link)
        ], function(i,n){
          excerpt.append(n);
        });
      }
    }
    $(this).data('full', $(this).html());
    $(this).data('excerpt', excerpt);
  });
  
  accordion.triggers.each(function(i){
    // extend each content area object with some custom methods.
    $.extend(this, {
      openclass: 'accordion_trigger_open',
      closedclass: 'accordion_trigger_closed',
      index: parseInt($(this).attr("id").split(accordion.trigger_class + "_")[1]),
      // return DOM element (not jQuery object) for this trigger's content area
      contentarea: function(){
        return $("#" + accordion.contentarea_class + "_" + this.index)[0];
      },
      markAsOpen: function(){
        return $(this).removeClass(this.closedclass).addClass(this.openclass);
      },
      markAsClosed: function(){
        return $(this).removeClass(this.openclass).addClass(this.closedclass);
      },
      collapse: function(){
        return this.contentarea().collapse();
      },
      expand: function(){
        return this.contentarea().expand();
      },
      toggle: function(){
        return this.contentarea().toggle();
      }
    });
    // attach the accordion behavior to the triggers
    $(this).click(function(){
      this.toggle();
    });
  });
  
  accordion.contentareas.each(function(){
    
  });
};

Accordion.prototype = {
  trigger_class: "accordion_trigger",
  contentarea_class: "accordion_contentarea",
  chars_to_show: 250,
  options: {
    excerpt_separator: 'hr',
    more_link: false
  },
  triggers: [],
  contentareas: [],
  expandAll: function(){
    this.triggers.each(function(){
      this.expand();
    });
  },
  collapseAll: function(){
    this.triggers.each(function(){
      this.collapse();
    });
  },
  toggleAll: function(){
    this.triggers.each(function(){
      this.toggle();
    });
  }
};