/**
 * @author Nathan Kelly - http://www.nathan-kelly.com/
 * @copyright 2009 Nathan Kelly
 * @package nk-starrating
 * @version 1.0.0
 * @url http://projects.nathan-kelly.com/nk-starrating/
 * @integration
 *  can be integrated with nk-lightbox-1.0.4.js
 * @dependencies 
 * 	prototype.js 1.6.0.3+ (http://www.prototypejs.org/)
 *	scriptaculous.js 1.8.2+ (http://script.aculo.us/)
 * @license
 *	Creative Commons Attribution 2.5 Australia License
 *	http://creativecommons.org/licenses/by/2.5/au/
 */

nk_init_starrating = Class.create({
	initialize: function (integrated, o) {
		this.o = Object.extend({
			_rootClass:		'ui-comp-object',
			_starSize:		20,
			_animate:		true,
			_morphSpeed:	0.2,
			_integrated:	integrated
		}, o || {});
		// thats it dont edit below unless you need to
		// check if this script was triggered by another libnk script
		if ( this.o._integrated ) {
			new nk_starrating($(this.o._integrated), this.o);
		} else {
			if ( !$$('.' + this.o._rootClass) ) { return; }
			var roots = $$('.' + this.o._rootClass);		
			for ( var i = 0; i < roots.length; i++ ) {		
				new nk_starrating(roots[i], this.o);
			}
		}
	}
});

nk_starrating = Class.create({
	initialize: function(root, o) {
		this.o = o;	
		this._root = root;
		
		if ( !this.o._integrated ) {
			this._stars = root.down('form') ? root.down('form') : null;			
		} else {
			this._stars = root;	
		}
		
		this._starsMax = this._stars.select('label').length;
		this._baseWidth = (this.o._starSize * this._starsMax);		
		this._starsKey  = this._stars.down('input^[name=key]').value;
		this._starsParent  = this._stars.down('input^[name=parent]').value;
		
		this._voteCast = this._stars.className.match(/ui-vote-cast/) ? true : false;
		this._currScore = (this._stars.down('input^[name=ave]').value * this.o._starSize);
		
		if ( this.o._integrated ) {
			this._tmpRoot = $('ui-rate-object-' + this._starsKey);
			this._voteCast = this._tmpRoot.className.match(/ui-vote-cast/) ? true : false;
			if ( this._voteCast === true ) { this._stars.addClassName('ui-vote-cast'); }
			this._currScore = (this._tmpRoot.down('input^[name=ave]').value * this.o._starSize);
		}
		
		// first we hide the label spans and inputs because we won't be using them visually
		this._stars.select('input', 'span').each( function (e) {}).invoke('hide');
			
		if ( !this.o._integrated ) {			
			this._stars.addClassName('ui-stars').setStyle({ width: this._baseWidth + 'px', height: this.o._starSize + 'px' });
			this._stars.down('div').addClassName('ui-stars-a').setStyle({ width: this._baseWidth + 'px', height: this.o._starSize + 'px' });		
			this._stars.insert({ top: Builder.node('div', {className: 'ui-stars-c'})});
			this._stars.insert({ top: Builder.node('div', {className: 'ui-stars-b'})});
		}
		
		this._starsA = this._stars.down('div.ui-stars-a');
		this._starsB = this._stars.down('div.ui-stars-b');
		this._starsC = this._stars.down('div.ui-stars-c');
		
		this._starsB.setStyle({ width: this._currScore + 'px', height: this.o._starSize + 'px' });
		this._starsC.setStyle({ width: this._currScore + 'px', height: this.o._starSize + 'px' });
		
		this._labels = this._stars.select('label');
		for ( i = 0; i < this._labels.length; i++ ) {
			this._labels[i].setStyle({ width: this.o._starSize + 'px', height: this.o._starSize + 'px' });
		}
		
		if ( this._voteCast === false ) {
			this._starsA.observe( 'mouseover', this._mouseOver.bindAsEventListener(this) );
			this._starsA.observe( 'mouseout', this._mouseOut.bindAsEventListener(this) );
			this._starsA.observe( 'click', this._click.bindAsEventListener(this) );
		}
	},
	
	_mouseOver: function (e) {
		Event.stop(e);
		if ( !this._stars.className.match(/ui-vote-cast/) ) {
			this._stars.addClassName('ui-stars-over');
			var elm = Event.findElement(e, 'label');
			var w = this.getStarPosition(elm);		
			if ( this.o._animate === true ) {
				new Effect.Morph( this._starsC, {
					style: 'width:' + w + 'px;',
					duration: this.o._morphSpeed
				});
			} else {
				this._starsC.setStyle({ width: w + 'px' });
			}
		}
	},
	
	_mouseOut: function (e) {
		Event.stop(e);
		if ( !this._stars.className.match(/ui-vote-cast/) ) {					
			this._stars.removeClassName('ui-stars-over');
			var elm = Event.findElement(e, 'label');
			if ( this.o._animate === true ) {
				new Effect.Morph( this._starsC, {
					style: 'width:' + this._currScore + 'px;',
					duration: this.o._morphSpeed
				});
			} else {
				this._starsC.setStyle({ width: this._currScore + 'px' });
			}
		}
	},
	
	_click: function (e) {
		Event.stop(e);
		if ( !this._stars.className.match(/ui-vote-cast/) ) {
			this._stars.addClassName('ui-vote-cast');
			
			var elm = Event.findElement(e, 'label');
			var average = elm.down('input').value;
			var newScore = average * this.o._starSize;
			this._starsC.setStyle({ width: newScore + 'px' });
	
			if ( this.o._animate === true ) {
				new Effect.Pulsate( this._starsC, {
					pulses: 3,
					duration: 0.6
				});
			}
			
			var options = {
				method: 'post',
				parameters: {
					vote: average,
					key: this._starsKey,
					parent: this._starsParent
				},
				onSuccess: this._onSuccess.bind(this),
				onFailure: this._onFailure.bind(this)
			};
	
			new Ajax.Request( ajaxObjectRatingURL, options );
		}
	},
	
	_onSuccess: function(transport) {
		var resp = transport.responseText.split(',');
		var votes = resp[0];
		var newAverage = resp[1];
		var newScore = newAverage * this.o._starSize;
		this._stars.down('input^[name=ave]').value = newAverage;
		if ( this.o._animate === true ) {
			new Effect.Morph( this._starsB, {
				style: 'width:' + newScore + 'px;',
				duration: this.o._morphSpeed,
				afterFinish: (function () {
					new Effect.Morph( this._starsC, {
						style: 'width:' + newScore + 'px;',
						duration: this.o._morphSpeed
					})
				}).bind(this)
			});
		} else {
			this._starsB.setStyle({ width: newScore + 'px' });
			this._starsC.setStyle({ width: newScore + 'px' });
		}
		
		if ( this.o._integrated ) {
			this._tmpRoot = $('ui-rate-object-' + this._starsKey);
			this._tmpRoot.addClassName('ui-vote-cast');
			this._tmpRoot.down('input^[name=ave]').value = newAverage;
			this._tmpRoot.down('div.ui-stars-b').setStyle({ width: newScore + 'px' });
			this._tmpRoot.down('div.ui-stars-c').setStyle({ width: newScore + 'px' });
		}
	},
	
	_onFailure: function(transport){
		alert('Something went wrong [' + transport.status + ']');
	},
	
	getStarPosition: function (elm) {		
		var pos = $(elm).positionedOffset();		
		var width = pos.left + this.o._starSize;		
		return width;
	}
});

document.observe('dom:loaded', function () { new nk_init_starrating(); });
