/**
 * dql.starrating.js
 *
 * Given a container that contains radio buttons, stars are shown that can be used to set a value on the radio buttons.
 */

/*global jQuery */

"use strict";

(function ($) {

	function StarRating(starContainer, conf) {
		var publ = {}, priv = {};

		priv.defaults = {
			starClass: 'starRating',
			starSelectedClass: 'starRatingSelected',
			onSetValue: null
		};

		priv.init = function (starContainer, conf) {
			priv.initVariables();
			priv.loadSettings(conf);
			priv.storeContainer(starContainer);

			if (!priv.containerFound()) {
				return;
			}

			priv.findRadioButtons();
			priv.hideRadioButtons();
			priv.createStars();
			priv.loadDefaultState();
			priv.addEventHandlers();
		};


		priv.initVariables = function () {
			priv.settings      = {};
			priv.starContainer = null;
			priv.radioButtons  = [];
			priv.stars         = [];
		};


		priv.loadSettings = function (conf) {
			priv.settings = $.extend(priv.defaults, conf);
		};


		priv.storeContainer = function (starContainer) {
			priv.starContainer = $(starContainer);
		};


		priv.containerFound = function () {
			return priv.starContainer.length;
		};


		priv.findRadioButtons = function () {
			$('input[type=radio]', priv.starContainer).each(function () {
				priv.radioButtons[priv.radioButtons.length] = $(this);
			});
		};


		priv.hideRadioButtons = function () {
			$(priv.radioButtons).each(function (i) {
				priv.radioButtons[i].hide();
			});

			$('label', priv.starContainer).each(function () {
				$(this).hide();
			});
		};


		priv.createStars = function () {
			var temp = '<div class="' + priv.settings.starClass + '"></div>';

			$(priv.radioButtons).each(function (i) {
				priv.radioButtons[i].after(temp);
				priv.stars[i] = priv.radioButtons[i].next('.' + priv.settings.starClass);
			});
		};


		priv.loadDefaultState = function () {
			var stateSet = false;

			$(priv.radioButtons).each(function (i) {
				if (priv.radioButtons[i].attr('checked') === true) {
					priv.setRating(i);
					stateSet = true;
				}
			});

			if (!stateSet) {
				priv.clearStars();
			}
		};


		priv.setRating = function (index) {
			priv.selectStars(index);
			priv.setSelectedRadio(index);
			if (typeof priv.settings.onSetValue === 'function') {
				priv.settings.onSetValue(publ);
			}
		};


		priv.selectStars = function (index) {
			$(priv.stars).each(function (i) {
				if (i <= index) {
					priv.stars[i].addClass(priv.settings.starSelectedClass);
				} else {
					priv.stars[i].removeClass(priv.settings.starSelectedClass);
				}
			});
		};


		priv.setSelectedRadio = function (index) {
			priv.radioButtons[index].attr('checked', true);
		};


		priv.clearStars = function () {
			$(priv.stars).each(function (i) {
				priv.stars[i].removeClass(priv.settings.starSelectedClass);
			});
		};


		priv.addEventHandlers = function () {
			$(priv.stars).each(function (i) {
				priv.stars[i].bind('mouseenter', function () {
					priv.selectStars(i);
				}).bind('mouseout', function () {
					priv.loadDefaultState();
				}).bind('click', function () {
					priv.setRating(i);
				});
			});
		};


		publ.getValue = function () {
			var value = 0;

			$(priv.radioButtons).each(function (i) {
				if (priv.radioButtons[i].attr('checked') === true) {
					value = i + 1;
				}
			});

			return value;
		};


		priv.init(starContainer, conf);


		return publ;
	}

	$.fn.starRating = function (conf) {
		var instances = [];

		this.each(function () {
			instances.push(new StarRating(this, conf));
		});

		return instances.length === 1 ? instances[0] : instances;
	};

}(jQuery));
