(function ($) {

$.fn.extend({
	singleSlider: function (settings) {
		var formatPrefix = '',
			format = function (value, prefix) {
				value += '';
				x = value.split('.');
				x1 = x[0];
				x2 = x.length > 1 ? '.' + x[1] : '';
				var rgx = /(\d+)(\d{3})/;
				while (rgx.test(x1)) {
					x1 = x1.replace(rgx, '$1' + ',' + '$2');
				}
				return prefix ? (prefix + x1 + x2) : (x1 + x2);
			},
			slide = function (e, ui) {
				var value = $(this).parents('label').find('ul li:eq(' + (ui.value - 1) + ') a').attr('title'),
					name = $(this).parents('label').find('ul li:eq(' + (ui.value - 1) + ') a').text();
				
				$(this).parents('label').find('ul li:eq(' + (ui.value - 1) + ')').addClass('selected').siblings().removeClass('selected');
				$(ui.handle).attr('title', name);
				$('.curVal span', $(ui.handle).parents('label')).text(name);
				$('input[type=hidden]', $(ui.handle).parents('label')).attr('value', value);
				$(this).parents('form').change();
			};
		
		return $(this).each(function () {
			var slider = $('.singleSlider', this).slider({
				orientation: 'horizontal',
				min: parseInt($('input[type=hidden]', $(this).parents('label')).attr('value'), 10),
				max: parseInt($('input[type=hidden]', $(this).parents('label')).attr('rel'), 10),
				step: 1,
				slide: slide
			}).hover(function () {
				$(this).addClass('ui-slider-hover');
			}, function () {
				$(this).removeClass('ui-slider-hover');
			});
			
			$('.singleSlider .ui-slider-handle', this).hover(function () {
				$(this).addClass('ui-slider-handle-hover');
			}, function () {
				$(this).removeClass('ui-slider-handle-hover');
			});
			
			$('ul li', this).click(function () {
				$(slider).slider('value', parseInt($('a', this).attr('rel'), 10));
				slide.apply($(this)[0], [{}, {
					handle: $('.ui-slider-handle', slider)[0],
					value: parseInt($('a', this).attr('rel'), 10)
				}]);
				return false;
			});
		});
	},
	rangeSlider: function (settings) {
		var handle,
			handleParent,
			slider,
			prfx,
			val,
			handleValue,
			curMin,
			curMax,
			formatPrefix = '',
			format = function (value, prefix) {
				value += '';
				x = value.split('.');
				x1 = x[0];
				x2 = x.length > 1 ? '.' + x[1] : '';
				var rgx = /(\d+)(\d{3})/;
				while (rgx.test(x1)) {
					x1 = x1.replace(rgx, '$1' + ',' + '$2');
				}
				return prefix ? (prefix + x1 + x2) : (x1 + x2);
			},
			toL100Km = function (mpg) {
				return (Math.round(235.2146 / mpg * 10) / 10);
			},
			toKilometers = function (miles) {
				return Math.round(miles / 0.6214);
			},
			slide = function (e, ui) {
				handle = $(ui.handle);
				handleParent = $(ui.handle).parents('label');
				slider = $(ui.handle).parent();
				prfx = $(handleParent).hasClass('price') ? '$' : '';
				
				// MPG sliders in Canadian locales need to display L/100km, underlaying MPG values are not converted
				// i.e. form submissions happen in MPG but the user sees L/100km
				if ($(slider).is('.l100km')) {
					val = toL100Km(ui.value);
				} else if ($(slider).is('.kilometerage')) {
					val = toKilometers(ui.value);
				} else {
					val = ui.value;
				}
				
				
				handleValue = !$(handleParent).hasClass('year') ? format(val, prfx) : val;
				// sometimes an array is passed, so we use its first item
				if (handleValue instanceof Array && handleValue.length) {
					handleValue = handleValue[0];
				} else if (handleValue instanceof Array) {
					handleValue = 0;
				}
				
				$(handle).attr('title', handleValue);
				$(($(handle).hasClass('ui-slider-handle-min') ? '.min' : '.max') + 'Val span', handleParent).text(handleValue);
				$($(handle).hasClass('ui-slider-handle-min') ? 'input[name*=min]' : 'input[name*=max]', handleParent).attr('value', ui.value);
			};
		
		return $(this).each(function () {
			var min = parseInt($('input[name*=min]', $(this).parents('label')).attr('value'), 10),
				max = parseInt($('input[name*=max]', $(this).parents('label')).attr('value'), 10),
				step = 1;
			
			// ensure stepping makes sense for the given range
			if ((max - min) > 100000) {
				step = 1000;
			} else if ((max - min) > 10000) {
				step = 100;
			}
			
			$('.rangeSlider', this).slider({
				min: min,
				max: max,
				step: step,
				values: [parseInt($('input[name*=min]', $(this).parents('label')).attr('value'), 10), parseInt($('input[name*=max]', $(this).parents('label')).attr('value'), 10)],
				range: true,
				slide: slide,
				stop: function(e, ui) {
					$(this).parents('label').find('input').change();
					$(this).parents('form').change();
				}
			}).bind('update.slider', function (e) {
				curMin = $(this).slider('values', 0);
				curMax = $(this).slider('values', 1);
				// need a way to explicitly call "update" since 'values' doesn't call slide, start, or stop
				slide.apply(this, [e, {
					handle: $('.ui-slider-handle-min', this),
					value: curMin
				}]);
				slide.apply(this, [e, {
					handle: $('.ui-slider-handle-max', this),
					value: curMax
				}]);
			}).trigger('update.slider');
			
			$('.rangeSlider', this).parents('label').hover(function () {
				$(this).addClass('ui-slider-hover');
			}, function () {
				$(this).removeClass('ui-slider-hover');
			});
			
			$('.rangeSlider .ui-slider-handle', this).hover(function () {
				$(this).addClass('ui-slider-handle-hover');
			}, function () {
				$(this).removeClass('ui-slider-handle-hover');
			});
			
			$('.rangeSlider a', this).click(function () { return false; });
		});
	}
});

$(function () {
	$('.rangeSlider').parent().rangeSlider();
	$('.singleSlider').parent().singleSlider();
});

})(jQuery);
