/**
 * RabidRatings - Simple and Pretty Ratings for Everyone
 * JavaScript functionality requires MooTools version 1.2 <http://www.mootools.net>.
 * 
 * Full package available at <http://widgets.rabidlabs.net/ratings>.
 *
 * NOTE: The included JavaScript WILL ONLY WORK WITH MOOTOOLS.  It will not work if any other JavaScript
 * framework is present on the page.
 *
 * Current MooTools version: 1.2
 *
 * @author Michelle Steigerwalt <http://www.msteigerwalt.com>
 * @copyright 2007, 2008 Michelle Steigerwalt
 * @license LGPL 2.1 <http://creativecommons.org/licenses/LGPL/2.1/>
 */

var RabidRatings = new Class({

	Implements: Options,
	
	options: {
		url: null,
		leftMargin: 0,  /* The width in pixels of the margin before the stars. */
		starWidth: 17,  /* The width in pixels of each star. */
		starMargin: 4,  /* The width in pixels between each star. */
		scale: 5,       /* It's a five-star scale. */
		snap: 1         /* Will snap to the nearest star (can be made a decimal, too). */
	},
	
	initialize: function(options) {
		
		this.setOptions(options);
		var activeColor = this.options.activeColor;
		var votedColor  = this.options.votedColor;
		var fillColor   = this.options.fillColor;
		this.onVote   = options.onvote;
		this.onUpdateText   = this.options.onupdatetext;

		$$('.rabidRating').each(this.initEl.bind(this));
	},

	initEl: function(el) {
		el.id = el.getAttribute('id');
		el.wrapper = el.getElement('.wrapper');
		el.textEl = el.getElement('.ratingText');
		el.offset = el.getPosition().x;
		el.fill = el.getElement('.ratingFill');
		//el.starPercent = this.getStarPercent(el.id);
		el.starPercent = 0;
		//el.ratableId   = this.getRatableId(el.id);
		el.ratableId   = 0;
		el.currentFill = this.getFillPercent(el.starPercent);
		el.morphFx = new Fx.Styles(el.fill, {'link':'chain'});
		el.widthFx = new Fx.Style(el.fill, 'width', {link: 'chain'});
		
		el.toggleVoted = function() {
			if (el.voted) {
				el.morphFx.start({'background-color': '#0069ff'});
				//el.addClass('ratingVoted');			
				el.wrapper.setStyle('cursor', 'default');
			}
			else {
				el.morphFx.start({'background-color': '#ff0000'});			
				//el.removeClass('ratingVoted');			
				el.wrapper.setStyle('cursor', 'pointer');
			}	
		}.bind(this);
		
		this.fillVote(el.starPercent, el, false);

		el.mouseCrap = function(e) { 
			e = new Event(e);
			if (!el.voted) {
				var fill = e.client.x - el.offset;
				var fillPercent = this.getVotePercent(fill);
				var step;
				if (this.options.snap === 0) step = 1;
				else step = (100 / this.options.scale) * this.options.snap;
				var nextStep = Math.floor(fillPercent / step) + 1;
				this.fillVote(nextStep * step, el, el.voted);
			}	
		}.bind(this);
		el.wrapper.addEvent('mouseenter', function(e) { 
			if (!el.voted) {
				el.morphFx.start({'background-color': '#ffa800'});
				el.wrapper.addEvent('mousemove', el.mouseCrap);
			}	
		});

		el.wrapper.addEvent('mouseleave', function(e) {
			if (!el.voted) {
				el.removeEvent(el.mouseCrap);
				el.morphFx.start({'background-color': '#ff0000'});
				el.widthFx.start(el.currentFill);
			}	
		});		
		
		el.wrapper.addEvent('click', function(e) {
			if (!el.voted) {
				el.oldFill = el.currentFill;
				el.currentFill = el.newFill;
				//el.morphFx.start({'background-color': '#0069ff'});
				//el.wrapper.removeEvents();
				//el.addClass('ratingVoted');
				//el.textEl.addClass('loading');
				var votePercent = this.getVotePercent(el.newFill);
				
				if (this.onVote) {
					this.onVote(votePercent);
				}
			}	
		}.bind(this));

		el.updateText = function(text, error) {
			//el.textEl.removeClass('loading');
			if (error) { el.showError(text); return false; }
			el.textEl.setText(text);
		};

		el.showError = function(error) {
			el.textEl.addClass('ratingError');
			oldTxt = el.textEl.getText();
			el.textEl.setText(error);
			(function() {
				el.textEl.setText(oldTxt);
				el.textEl.removeClass('ratingError');
				this.fillVote(el.oldFill, el, el.voted);				
			}.bind(this)).delay(1000);
		}.bind(this);

		el.showSuccess = function(text) {
			el.textEl.addClass('ratingError');
			oldTxt = el.textEl.getText();
			el.textEl.setText(text);
			(function() {
				el.textEl.setText(oldTxt);
				el.textEl.removeClass('ratingError');
			}.bind(this)).delay(1000);
		}.bind(this);
	
	},
	
	fillVote: function(percent, el, voted) {
		el.voted = voted;
		el.newFill = this.getFillPercent(percent);

		if (this.getVotePercent(el.newFill) > 100) { el.newFill = this.getFillPercent(100); }
		el.fill.setStyle('width', el.newFill);
		el.toggleVoted();
	},

	startVote: function(percent, el, voted) {
		el.voted = voted;
		el.offset = el.getPosition().x;
		el.newFill = this.getFillPercent(percent);
		el.currentFill = el.newFill;		

		if (this.getVotePercent(el.newFill) > 100) { el.newFill = this.getFillPercent(100); }
		el.fill.setStyle('width', el.newFill);
		el.toggleVoted();
	},

	getStarPercent: function(id) {
		/* Format = anyStringHere-<id>-<float(currentStars)>_(scale); 
		 * Example: rabidRatings-5-3_5 //Primary key id = 5, 3/5 stars. */
		var stars = id.match(/(\d*)-(\d*\.?\d+)_(\d*\.?\d+)$/);
		var ratableId = stars[1].toFloat();
		var score = stars[2].toFloat();
		var scale = stars[3].toFloat();
		var percent =  (score / scale) * 100;
		return percent;
	},

	getFillPercent: function (starPercent) {
		return (starPercent/100)*((this.options.starWidth+this.options.starMargin)*this.options.scale) + this.options.leftMargin;
	},

	getVotePercent: function(divPosition) {
		var starsWidth = (this.options.starWidth+this.options.starMargin)*this.options.scale;
		var offset = this.options.leftMargin;
		var starPosition = divPosition - this.options.leftMargin;
		var percent = (starPosition / starsWidth * 100).round(2);
		return percent;
	},

	getRatableId: function(id) {
		var stars = id.match(/(\d*)-(\d*\.?\d+)_(\d*\.?\d+)$/);
		return stars[1];
	},
	
	setOptions: function(){
	return;
		this.options = $merge($(this.options, arguments));
		if (!this.addEvent) return this;
		for (var option in this.options){
			if ($type(this.options[option]) != 'function' || !(/^on[A-Z]/).test(option)) continue;
			this.addEvent(option, this.options[option]);
			delete this.options[option];
		}
		return this;
	}

});
