/**
 * @copyright Affinitive, LLC (support@beaffinitive.com)
 * @author Rob Marscher (rmarscher@beaffinitive.com)
 * @package Enclave
 * modified from http://php.scripts.psu.edu/rja171/widgets/rating.php
 * which in turn was taken from http://sandbox.wilstuckey.com/jquery-ratings/
 * 
 * TODO: support full star increments - this seems to only work with half increments
 *       abstract the star part of it keeping the core rating part
 *       this would allow support for non-star based controls (thumbs up/down, plus minus, etc)
 * 
 * NOTE: the "cancel" option is still in here... but it's not supported currently 
 */
jQuery.fn.rating = function(url, options) {
	var rating;
	this.each(function() {
		var x = null;
		rating = new Affinitive_Rating(this, url, options);
		rating.init();
		this.affRating = rating;
	});
	return this;
};
Affinitive_Rating = function(container, url, options) {
	if (url === null) { return; }
	
	this.settings = {
		ratingType      : 'star', // allow possibility for other rating types - not sure how realistic this will be
		itemType        : null, // type of item being rated - not used yet, but here if we need it
		itemId          : null, // id of item being rated - not used yet, but here if we need it
		url             : url,  // post changes to 
		increment       : 1,    // value to increment by
		maxvalue        : 5,    // max number of stars
		curvalue        : 0,    // currentRating value
		curvalueType    : "overallValue",
		overallValue    : 0,    // overallRating value
		overallVotes    : 0,    // total votes
		userValue       : 0,    // userRating value
		authorized      : true, // rating is authorized
		groupOverall    : null, // optional container to an overall rating that needs to be refreshed 
		lr: function(container) { 
			if (!fpglobals.loggedIn) {
				lr(container, 'boxB', null, 'popAbsoluteLeft');
				return false;
			} else {
				return true;
			} 
		} // function to call to check login status, must return boolean
	};
	
	if (options) {
		jQuery.extend(this.settings, options);
	}
	jQuery.extend(this.settings, {cancel: (this.settings.maxvalue > 1) ? true : false});

	this.container = container;
	this.jContainer = jQuery(container);
	this.initialized = false; 
};
Affinitive_Rating.prototype = {
	init: function() {
		this.settings.increment = (this.settings.increment < 0.75) ? 0.5 : 1;
		// this.initialized allows init to be run again after new settings are loaded
		if (this.initialized === false) {
			this._generateControls();
		}
		// set curvalue based on curvalueType
		if (this.settings.curvalueType == "overallValue") {
			this.settings.curvalue = this.settings.overallValue;
		} else {
			this.settings.curvalue = this.settings.userValue;
		}

		// set this to affRating since "this" is overridden the event context with the DomElement
		var affRating = this;
		if (this.settings.authorized) {
			this.jContainer.removeClass('not-authorized');
			this.controls
				.mouseover(function() {
					affRating.drain();
					affRating.fill(this);
				})
				.mouseout(function() {
					affRating.drain();
					affRating.reset();
				})
				.focus(function() {
					affRating.drain();
					affRating.fill(this);
				})
				.blur(function() {
					affRating.drain();
					affRating.reset();
				});
		
			this.controls.click(function() {
				if (affRating.settings.lr(affRating.container)) {
					if (affRating.settings.cancel === true){
						affRating.settings.curvalue = (affRating.controls.index(this) * affRating.settings.increment) + affRating.settings.increment;
						jQuery.post(
							affRating.settings.url,
							{"rating": jQuery(this).children('a')[0].href.split('#')[1]},
							function(response, status) {
								if (status == 'success') {
									if (affRating.settings.groupOverall !== null) {
										affRating.settings.groupOverall.affRating.refresh();
									}
									affRating.update(response);
								}
							},
							"json"
						);
						return false;
					} else if (affRating.settings.maxvalue == 1) {
						affRating.settings.curvalue = (affRating.settings.curvalue === 0) ? 1 : 0;
						jQuery(this).toggleClass('on');
						jQuery.post(
							affRating.settings.url,
							{"rating": jQuery(this).children('a')[0].href.split('#')[1]},
							function(response, status) {
								if (status == 'success') {
									affRating.jContainer.parent().html(response);
								}
							},
							"json"
						);
						return false;
					}
				} else {
					return false;
				}
			});
			// cancel button events
			if (this.cancel) {
				this.cancel
					.mouseover(function() {
						affRating.drain();
						jQuery(this).addClass('on');
					})
					.mouseout(function() {
						affRating.reset();
						jQuery(this).removeClass('on');
					})
					.focus(function() {
						affRating.drain();
						jQuery(this).addClass('on');
					})
					.blur(function() {
						affRating.reset();
						jQuery(this).removeClass('on');
					});
	
				// click events.
				this.cancel.click(function() {
					affRating.drain();
					affRating.settings.curvalue = 0;
					jQuery.post(affRating.settings.url, {
						"rating": jQuery(this).children('a')[0].href.split('#')[1] 
					});
					return false;
				});
			}
		} else {
			this.jContainer.addClass('not-authorized');
			this.controls.unbind();
			this.controls.click(function() { return false; });
		}
		this.drain();
		this.reset();
		this.initialized = true;
	},
	_generateControls: function() {
		if (this.settings.ratingType == 'star') {
			this._generateStarControls();
		}
	},
	_generateStarControls: function() {
		var s = 0;
		this.jContainer.attr("title", this.settings.overallValue + "/" + this.settings.maxvalue + " out of " + this.settings.overallVotes + " vote" + (this.settings.overallVotes != 1 ? "s" : ""));
		for (var i = 0; i <= this.settings.maxvalue; i++) {
			if (i === 0) {
				if (this.settings.cancel === true) {
					var div = '<div class="cancel"><a href="#0" title="Cancel Rating">Cancel Rating</a></div>';
					this.jContainer.empty().append(div);
				}
			} else {
				var jQuerydiv = jQuery('<div class="star"></div>')
					.append('<a href="#'+i+'">'+i+'</a>')
					.appendTo(this.container);
				if (this.settings.increment == (0.5)) {
					if (s % 2) {
						jQuerydiv.addClass('star-left');
					} else {
						jQuerydiv.addClass('star-right');
					}
				}
			}
			i = i - 1 + this.settings.increment;
			s++;
		}
		this.controls = this.jContainer.children('.star');
		this.cancel = this.jContainer.children('.cancel');
	},
	update: function(settings) {
		if (settings) {
			jQuery.extend(this.settings, settings);
			this.init();
		}
	},
	refresh: function() {
		var affRating = this;
		jQuery.getJSON(this.settings.url, function(json) {affRating.update(json);});
	},
	fill: function(el) { // fill to the current mouse position.
		var index = this.controls.index(el) + 1;
		this.controls
			.children('a').css('width', '100%').end()
			.slice(0,index).addClass('hover').end();
	},
	drain: function() { // drain all the stars.
		this.controls
			.filter('.on').removeClass('on').end()
			.filter('.hover').removeClass('hover').end();
	},
	reset: function() { // Reset the stars to the default index.
		this.controls.slice(0, this.settings.curvalue / this.settings.increment).addClass('on').end();
	},
	setValue: function(value) {
		this.settings.curvalue = value;
		this.drain();
		this.reset();
	},
	showUserValue: function() {
		this.settings.curvalueType = 'userValue';
		this.setValue(this.settings.userValue);
	},
	showOverallValue: function() {
		this.settings.curvalueType = 'overallValue';
		this.setValue(this.settings.overallValue);
	},
	toggleValueType: function() {
		if (this.settings.curvalueType == 'overallValue') {
			this.showUserValue();
		} else {
			this.showOverallValue();
		}
	}
};
