

var Rating = (function(){
	
	var Dom = YAHOO.util.Dom, Event = YAHOO.util.Event, Lang = YAHOO.lang;
	
	var rater = function(el, cfg) {
		rater.prototype.init.call(this, el, cfg);
	};
	
	rater.prototype = {
		lastXY: [0,0],
		
		stars: {},
		
		running: false,
		
		init: function (el, cfg) {
			if ( Lang.isString(el) )
				el = Dom.get(el);
			
			this.config = Lang.merge({
					snapTo: 20,
					roundTo: 'ceil'
			}, cfg||{});
			
			this.element = el;
			
			this.id = this.element.id;
			
			this.initElements();
			
			this.initEvents();
		},
		
		initElements: function() {
			
			var el = this.element.firstChild;
			
			do {
				
				if ( el && el.nodeType == 1 ) {
					if ( Dom.hasClass( el, 'rtg-stars-average' ) )
						this.stars.average = el;
					else if ( Dom.hasClass(el, 'rtg-stars-total' ) )
						this.stars.total = el;
					else if ( Dom.hasClass(el, 'rtg-stars-active' ) )
						this.stars.active = el;
				}
				
			} while( (el = el.nextSibling) );
			
		},
		
		initEvents: function() {
			
			Event.on( this.element, 'mouseover', this.start, this, true );
			Event.on( this.element, 'click', this.handleClick, this, true );
			
		},
		
		start: function()
		{
			if ( this.timeout && this.timeout.cancel ) {
				this.timeout.cancel();;
				this.timeout = false;
			}
			
			if ( this.running )
				return;
			
			Event.on( this.element, 'mousemove', this.handleMove, this, true );
			Event.on( this.element, 'mouseout', this.stop, this, true );
			
			this.xy = Dom.getXY(this.element);
			this.width = Dom.get(this.element).offsetWidth;
			
			this.hide('average').show('active');
		},
		
		stop: function()
		{
			var timeout = function () {
				Event.removeListener( this.element, 'mousemove', this.handleMove );
				
				this.hide('active').show('average');
				
				this.running = false;
			};
			
			//this.timeout = Lang.later( 1000, this, timeout );
			timeout.call(this);
		},
		
		update: function()
		{
			if ( this.running )
				return;
			
			var delta = [
				this.lastXY[0] - this.xy[0],
				this.lastXY[1] - this.xy[1]
			];
			
			var cur_width = this.getWidth('active'),
				new_width = Math.round((delta[0] / this.width) * 100);
				
			var width = this.calcWidth( new_width, cur_width );
			
			if ( width != cur_width )
				this.setWidth('active', width);
		},
		
		handleClick: function (evt)
		{
			var el = Event.getTarget(evt);
			
			if ( Dom.isAncestor( this.element, el ) ) {
				var form = Dom.getAncestorByTagName( this.element, 'form' );
				
				if ( form ) {
					if ( form.elements['data[Rating][rating]'] ) {
						var rating = form.elements['data[Rating][rating]'];
						
						rating.value = this.calc();
					}
					
					form.submit();
				}
			}
		},
		
		handleMove: function (evt)
		{
			this.lastXY = Event.getXY(evt);
			
			this.update();
		},
		
		calc: function (width)
		{
			return this.calcWidth( width || parseInt( this.getWidth( 'active' ), 10 ) );
		},
		
		calcWidth: function ( width )
		{
			var snapTo = this.config.snapTo;
			
			if ( width % snapTo === 0 )
				return width;
			
			var mod = width % snapTo;
			
			if ( mod > snapTo / 2 || this.config.roundTo == 'ceil' )
				return Math.round( width - mod + snapTo );
			
			return Math.round( width - mod );
		},
		
		getWidth: function (key)
		{
			return parseInt( this.getStyle(key, 'width'), 10 );
		},
		
		setWidth: function (key, width) 
		{
			this.style(key, {width: width + "%"});
		},
		
		hide: function (key)
		{
			return this.style(key, {display:'none'});
		},
		
		show: function (key)
		{
			return this.style(key, {display:'block'});
		},
		
		style: function (key, styles)
		{
			var el = this.getEl(key);
			
			if ( el )
			{
				for (var attr in styles)
					Dom.setStyle(el, attr, styles[attr]);
			}
			
			return this;
		},
		
		getStyle: function (key, attr)
		{
			var el = this.getEl(key);
			
			if ( el )
			{
				return Dom.getStyle(el, attr);
			}
			
			return false;
		},
		
		getEl: function (key)
		{
			var el = this.stars[key];
			
			return el;
		}
		
	};
	
	return {
		
		_elements: {},
		
		init: function (el) {
			
			if ( Lang.isString(el) )
				el = Dom.get(el);
			
			new rater(el);
			
		},
		
		watch: function () {
			
			var ids = [].slice.apply(arguments);
			
			for (var i = 0; i < ids.length; i++) {
				var el = ids[i];
				
				Event.onAvailable(el, Rating.init, el, Rating);
			}
		}
		
	}
})();



