/*
 *   RankStars v1.0
 *   Copyright (C) 2008, 2009 Intercon e-consulting, http://www.intercon.pl/
 *
 *   code: Pawel Piotrowski,
 *         Wojciech Polak
 */

(function ($) {

	var ua = {
		ie: (x = navigator.appVersion.match (/MSIE\s(\d+\.\d+)/)) ? true : false,
		ie6: x && x.length > 1 ? x[1] <= 6 : false
	};

	var defaults = {
		disabled: false,
		segWidth: 15,
		segHeight: 14,
		precision: [1, 0.5],
		segments: [5, 10],
		image: 'star.png',
		spacer: 'spacer.gif', /* empty image for ie6 transparency handling problem */
		emptyColor: '#ccc',
		starColor: '#f00',
		afterColor: '#00f',
		showLabels: true,
		labels: ['Poor', 'Nothing special', 'Good', 'Pretty cool', 'Awesome!'],
		defaultLabel: 'Average',
		id: '',
		url: 'bin/rankstars.php',
		postParam: 'note',
		rank: null,
		average: null,
		showAvg: true,
		cb: null,
		cbParams: {}
	};

	$.fn.rankStars = function (args) {
		var opts = $.extend ({}, defaults, args);
		return this.each (init);

		function init () {
			var obj = $(this);
			var o = {};
			o.a = createElm ('a', {href: 'javascript:void(0);'});
			o.s = createElm ('span');
			o.l = createElm ('label');
			o.a.appendChild (o.s);
			obj.append (o.a);
			obj.append (o.l);
			o.disabled = opts.disabled;
			o.rank = opts.rank;
			o.average = opts.average;
			obj.o = o;

			setLength ();
			setPrecision ();

			var attrs = {
				src: opts.image,
				alt: '',
				width: opts.segWidth,
				height: opts.segHeight,
				border: 0
			};

			for (var i = 0; i < opts.segments; i++) {
				if (ua.ie6) {
					attrs.src = opts.spacer;
					var img = createElm ('img', attrs);
					img.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"
								+ opts.image + "',sizingMethod='scale')";
				} else {
					var img = createElm ('img', attrs);
				}
				o.a.appendChild (img);
			}
    
			/* CSS */
			obj.css ({
				'width': opts.segments * opts.segWidth + 'px',
				'text-align': 'center'
			});
			$('a', obj).css ({
				'position': 'relative',
				'display': 'block',
				'background': opts.emptyColor,
				'z-index': 2,
				'height': opts.segHeight + 'px',
				'cursor': 'default'
			});
			$('span', obj).css ({
				'position': 'absolute',
				'top': 0,
				'left': 0,
				'display': 'block',
				'height': opts.segHeight + 'px',
				'background': opts.afterColor
			});
			$('img', obj).css ({
				'position': 'relative'
			});
			$('label', obj).css ({
			});

			o.posx = obj.position ().left;/*determine object position after it's css is established */
			if (typeof opts.rank == 'number') {
				o.rank = opts.rank;
				if (opts.showAvg)
					o.average = opts.rank;
				o.disabled = opts.disabled;
				validRank (obj, opts.rank);
				if (opts.showAvg) showLabel (obj);
			}
			else if (opts.url) {
				$.getJSON (opts.url, function (data) {
						if (data.id) opts.id = data.id;
						o.disabled = data.disabled;
						if (o.disabled) disable (obj);
						o.average = data.average;
						if (opts.showAvg)
							validRank (obj, data.average);
						if (opts.showAvg) showLabel (obj);
				});
			}
			if (!o.disabled)
				enable (obj);
		}

		//set precision
		function setPrecision () {
			var prec = validParams ('precision');
			if (opts.segments == 10) {
				prec = defaults.precision[0];
			}
			opts.precision = prec;
		}

		function setLength () {
			opts.segments = validParams ('segments');
		}

		function validParams (param) {
			var allowed = defaults[param];
			var param = parseFloat (opts[param], 10);
			for (var i = 0; i < allowed.length; i++) {
				if (param == allowed[i]) break;
			}
			if (isNaN (param) || i == allowed.length) {
				param = allowed[0];
			}
			return param;
		}

		function enable (obj) {
			obj.o.s.style.background = opts.starColor;
			$('a', obj).css ({'cursor' : 'pointer'});
			obj.o.a.onmousemove = function (event) {
				setUserRank (event, obj.o);
			};
			obj.o.a.onclick = function () {
				this.blur ();
				disable (obj);
				submitRank (obj);
			};
		}

		function disable (obj) {
			obj.o.a.onmousemove = null;
			obj.o.a.onclick = null;
			obj.css ({'opacity' : '0.9', 'filter' : 'alpha(opacity=90)'});
			$('a', obj).css ({'cursor' : 'default'})
			obj.o.disabled = true;
		}

		function submitRank (obj) {
			$.ajax ({
				type: 'POST',
				dataType: 'json',
				url: opts.url,
				data: 'id=' + opts.id + '&' + opts.postParam + '=' + obj.o.rank,
				success: function (data) { /*alert ('Thanks for rating!');*/
						if (data.status === 0) {
							setAvgRank (obj, data.average);
						}
				},
				error: function (request, status, thrown) { alert('Error: ' + (thrown ? thrown.message : '')); }
			});
		}

		function validRank (obj, rank) {
			if (isNaN (rank))	return;
			if (rank > opts.segments)
				rank = opts.segments;
			if (rank < 0)
				rank = 0;
			obj.o.rank = calcAverage (rank);
			setWidth (obj.o);
		}

		function calcPrecision (rank) {
			var tmp = Math.ceil (rank);
			if (tmp > Math.round (rank) && opts.precision < 1) {
				tmp -= opts.precision;
			}
			return tmp;
		}
    
		function calcAverage (rank) {
			var tmpRank = Math.floor (rank);    
			if (opts.precision < 1) {
				var tmp = Math.round ((rank - tmpRank) * 100);
				if (tmp < 25) {
				}
				else if (tmp < 75) {
					tmpRank += opts.precision;
				}
			}
			else {
				tmpRank = Math.round (rank);
			}
			return tmpRank;
		}

		function setWidth (o) {
			o.s.style.width = Math.round (o.rank * opts.segWidth) + 'px';
		}
    
		function showLabel (obj) {
			if (opts.showLabels && obj.o.l)
				obj.o.l.innerHTML = opts.defaultLabel + ': ' + obj.o.average;
		}

		function setAvgRank (obj, rank) {
			obj.o.s.style.background = opts.afterColor;
			opts.average = rank;
			obj.o.average = rank;
			if (opts.showAvg) {
				validRank (obj, rank);
				showLabel (obj);
			}
			if (typeof opts.cb == 'function') {
				opts.cbParams['RSRank'] = obj.o.rank;
				opts.cbParams['RSId'] = opts.id;
				opts.cb (opts.cbParams);
			}
		}

		function setUserRank (e, o) {
			var e = e || event;
			var x = e.clientX;
			var rank = (x - o.posx) / opts.segWidth;
			o.rank = calcPrecision (rank);
			setWidth (o);
			if (opts.showLabels && o.l && (lbl = opts.labels[Math.ceil(o.rank) - 1]))
				o.l.innerHTML = o.rank + ' - ' + lbl;
			else
				o.l.innerHTML = '';
		}

		function showPreloader () {
		}

		function createElm (name, attrs) {
			var elm = document.createElement (name);
			if (elm && attrs) {
				for (var i in attrs) {
					elm.setAttribute (i, attrs[i]);
				}
			}
			return elm;
		}
	};
})(jQuery);