(function( $ ) {
  $.fn.Rater = function(settings) {

settings = $.extend({
   ratingContSelector:    "div.star-rating",
   ratingContPrefix:    "rating-",
   ratingStatsContPrefix:   "stats-for-"
}, settings);

// return each of the submitted forms
return this.each(function(){
   
   var theForm =    this,      // the form
  theRatingConts =  $(settings.ratingContSelector, theForm), // the containers holding the select rating elements
  ratedForms = $.cookie("exp_rating-" + $(theForm).attr("name")),  // the existing cookie
  rated =    $(theForm).is(".rated") ? true : false   // everything is unrated by default

   console.log("Cookie: " + ratedForms);

   // if there is a cookie
   if(ratedForms && !rated){
  // match the current form.id and the users rating to the cookie string
  matchRegExp = new RegExp("(("+theForm.id+"):([1-5]))");
  rated = matchRegExp.exec(ratedForms);
   }

   // log the form status
   console.log("Form ID: " + theForm.id +" has "+ ((rated)?"been rated":"NOT been rated"));

   $(settings.ratingContSelector, theForm).each(function(){

  var theRatingCont =   $(this),    // The container that holds the select and the rating stats
    theRater =   $("select", theRatingCont).get(0), // The rating select box
    theRaterOpts = $("option", theRater),    // The rating options
    
    theRaterEntryId =   this.id.replace(settings.ratingContPrefix, ""),
    
    theStats =   $("#" + settings.ratingStatsContPrefix + theRaterEntryId),
    overallCountEl =  $(".overall_count", theStats),   // The number of ratings
    overallAvgEl = $(".overall_avg", theStats),   // The average rating
    overallSumEl = $(".overall_sum", theStats),   // The sum of all the ratings
    maxOverallSumEl =   $(".max_overall_sum", theStats), // The maximum sum of all the ratings
   
    overallCount = parseFloat(overallCountEl.html()), // The number of ratings
    overallAvg = parseFloat(overallAvgEl.html()), // The average rating
    overallSum = parseFloat(overallSumEl.html()), // The sum of all the ratings
    maxRating =  theRaterOpts.length,    // The maximum rating
    maxOverallSum =   maxRating * overallCount;    // The maximum sum of all the ratings

  console.log(theRatingCont);
  console.log("Rating Entry: " + theRaterEntryId);
  console.log("Searching For Sats Container... " + settings.ratingStatsContPrefix + theRaterEntryId);
  console.log("Stats: ");
  console.log(theStats);

  // create a new UL star rating container
  var starRater = $("<ul></ul>")
    .insertBefore(theRater)
    .hide()
    .addClass(this.className)
    .fadeIn("slow")
    .mouseover(function(){
   $("a.active", this).removeClass("active");
    });

  // create and append the current rating list item
  if(overallCount != 0){
    var currentRating = $("<li class='current-rating' style='width:" + (overallSum / maxOverallSum) * 100 + "%;'> Currently " + overallAvg + "/" + maxRating + " Stars.</li>");
  }
  else
  {
    var currentRating = $("<li class='current-rating' style='width:0%;'>Unrated!</li>");
  }
  starRater.append(currentRating);

  if(!rated){
    // create and append the rating anchors
    theRaterOpts.each(function(i){
   starRater.append("<li class='star-" + ( i + 1 ) + "'><a href='#' title='Give it a " + this.value + " Star Rating'>" + this.value + "</a></li>");
    });
  } else {
    $("#submission-status-for-" + theRaterEntryId).show();
  }

  $("a", starRater).click(function(){
    // set the anchor to active
    $(this).addClass("active").blur();
    // Get the clicked elements rating
    var rating = parseFloat($(this).html());
    // update the select element with the new value
    theRater.selectedIndex = rating - 1;
    
    // Get the latest cookie
    var ratedForms = $.cookie("exp_rating-" + $(theForm).attr("name")); // the existing cookie

    // if there is not a cookie
    if(!ratedForms){
   ratedForms = "|";
    }

    // Add the new form id and the rating to the front of the cookie
    // |theForm.id:rating|theForm.id:rating|
    $.cookie("exp_rating-" + $(theForm).attr("name"), ratedForms + theForm.id + ":" + rating + "|", {path: "/", expires: 365});
    
    // remove the mouseover event on the UL
    $(starRater).unbind("mouseover");

    // remove all the star links that are not active
    $("li a:not(.active)", starRater).parent().remove();

    // Update Stats for this rating
    overallCount++;
    overallSum += rating;
    maxOverallSum = overallCount * maxRating;
  
    overallCountEl.html(overallCount);
    overallSumEl.html(overallSum);
    maxOverallSumEl.html(maxOverallSum);
    overallAvgEl.html( ((overallSum / maxOverallSum ) * maxRating).toFixed(2) );

    currentRating.css({ "width": (overallSum / maxOverallSum ) * 100 + "%" });

    $('input[type=submit]', theForm).click();

    return false;
  });
   });

   // add classes to the form
   $(theForm).addClass("has-rateables" +
  // auto-submit or button-submit
  ((settings.autoSubmit)?" auto-submit":" button-submit") +
  // submitted or not-submitted
  ((rated)?" submitted":" not-submitted")
   );
});
  }
})(jQuery);