jQuery.fn.quizard = function(settings) {
  
  settings = jQuery.extend({
     questionsClass: 'questions',
     resultClass: 'result',
     optionClass: 'option',
     scrollClass: 'scroll',
     engine: 'range'
  }, settings);
  
  if (!settings.results) {
    return;
  }
  
  return this.each(function(){
    // Hide all results
    jQuery(this).find('.' + settings.resultClass).hide();
    var questions = jQuery(this).find('.' + settings.questionsClass + ' li');
    questions
      // Hide all questions by default
      .hide()
      // Show just the first question
      .filter(':first').show().end()
      // Add next/prev links to each one of the questions
      .each(function() {
        jQuery('<div class="' + settings.scrollClass + '"><a href="#" class="prev">Prev</a> <a href="#" class="next">Next</a></div>')
          .appendTo(jQuery(this))
          .each(function() {
            // Now remove the "Prev" link from the first question and change "Next" on the last one "Results"
            jQuery(this).parents('ol')
              .find('li:first-child .prev').remove().end()
              .find('li:last-child .next').removeClass('next').addClass('results').html('Results').end();
          })
          // Assign the paging event to each link, now that we've gotten rid of the ones we don't want.
          .find('a.next').bind('click', {settings: settings}, jQuery.quizard.nextClick).end()
          .find('a.prev').bind('click', {settings: settings}, jQuery.quizard.prevClick).end()
          .find('a.results').bind('click', {settings: settings, questions: questions}, jQuery.quizard.resultsClick).end();
      });
    
  });
};

jQuery.fn.quizardTotals = function (optionClass) {
  var total = 0;
  this.each(function() {
    jQuery(this).find('input.' + optionClass + ':checked').each(function() {
      total += parseInt(jQuery(this).val());
    });
  });
  return total;
};

// Our extra callback handlers for link clicking
jQuery.quizard = {
  nextClick : function(event) {
    event.preventDefault();
    jQuery(this)
      .parents('ol.' + event.data.settings.questionsClass)
        .find('li:visible').hide().end()
        .attr('start', jQuery(this).parents('li').childPos(2))  // The childNum is 0-based on the element visible when clicked
      .end()
      .parents('li').next().show();
  },
  prevClick : function(event) {
    event.preventDefault();
    jQuery(this)
      .parents('ol.' + event.data.settings.questionsClass)
        .find('li:visible').hide().end()
        .attr('start', jQuery(this).parents('li').childPos())
      .end()
      .parents('li').prev().show();
  },
  resultsClick : function(event) {
    event.preventDefault();
    // Hide all questions and show the appropriate results div(s)
    // We call out to whatever engine we're using, which returns a jQuery object of the results that apply
    jQuery(this).parents('.' + event.data.settings.questionsClass).hide();
    jQuery.quizard.engines[event.data.settings.engine](event.data).show();
  },
  engines: {
    range : function(data) {
      // Expand the results ranges into a simple lookup table
      var resultKey = [];
      for (var i=0; i < data.settings.results.length; i++) {
        for (var j=data.settings.results[i].start; j <= data.settings.results[i].end; j++) {
          resultKey[j] = data.settings.results[i].key;
        }
      }
      return jQuery('#' + resultKey[data.questions.quizardTotals(data.settings.optionClass)]);
    },
    max : function(data) {
      var totals = {};
      var max = 0;
      var shown = [];
      data.questions.each(function() {
        jQuery(this).find('input.' + data.settings.optionClass + ':checked').each(function() {
          if (! totals[jQuery(this).val()]) totals[jQuery(this).val()] = 0;
          totals[jQuery(this).val()] += 1;
        });
      });
      for (key in totals) {
        if (totals[key] > max) max = totals[key];
      }
      for (key in totals) {
        if (totals[key] == max) shown[shown.length] = '#' + data.settings.results[key];
      }
      return jQuery(shown.join(','));
    }
  }
};

jQuery.fn.childPos = function(n) {
  // Add to index, if you want to start from 1 for example
  return this.parent().children().index(this[0]) + (n || 0);
}

jQuery.fn.debug = function() {
  return this.each(function(){
    console.debug(this);
  });
};