// Rotates.org ColorShift 0.7 - by Lewis 'SEPTiMUS' Lane - www.rotates.org
// Excuse the less shitty (but still a bit shitty) JS :(
// 
// Requires:
// jQuery: http://www.jquery.com
// jQuery UI (sliders): http://jqueryui.com
// jQuery Cookies: http://code.google.com/p/cookies

var rotColShiftOpts = {
	hsl: {h: 4, s: 100, l: 50}, // default settings for hue (0-360), saturation (0-100) and brightness/luminescence (0-100)
	sliderAnimSpeed: 120, // speed of handle animation when clicking slider
	useCookies: true, // store cookies to remember user's colour choice
	cookieHours: 8760, // keep cookie alive for this many hours (default one year)
	// add your transforms below as an array of objects matching the format { selector: "#foo", offsets: {h: hue, s: saturation, l: lightness}, attributes: ["foo-color", "bar-background"] }
	cssTransforms: [
		{
			selector: "a, h2, h3, h4, h5",
			attributes: [
				"color"
			]
		},
		{
			selector: "a:hover",
			offsets: {
				h: +10,
				s: +20,
				l: +10
			},
			attributes: [
				"color"
			]
		},
		{
			selector: "#header, #searchsubmit",
			attributes: [
				"background-color"
			]
		},
		{
			selector: "h1",
			offsets: {
				l: -50
			},
			attributes: [
				"color"
			]
		},
		{
			selector: "img.chromakey",
			attributes: [
				"background-color"
			]
		}
	]
};

var ieStyle;

function setCookies(h,s,l) {
	if (rotColShiftOpts.useCookies) {
		var cookieOptions = { hoursToLive: rotColShiftOpts.cookieHours };
		$.cookies.set('rotates_hue', h, cookieOptions );
		$.cookies.set('rotates_saturation', s, cookieOptions );
		$.cookies.set('rotates_brightness', l, cookieOptions );
	}
}

// the following functions weren't written by me, as maths is very much _not_ my strong point

function huetorgb(m1, m2, hue) {
	var v;
	if (hue < 0) {
		hue += 1;
	}
	else if (hue > 1) {
		hue -= 1;
	}
	if (6 * hue < 1) {
		v = m1 + (m2 - m1) * hue * 6;
	}
	else if (2 * hue < 1) {
		v = m2;
	}
	else if (3 * hue < 2) {
		v = m1 + (m2 - m1) * (2/3 - hue) * 6;
	}
	else {
		v = m1;
	}
	return Math.round(255 * v);
}

function hsl2rgb(h, s, l) {
	var m1, m2, hue;
	var r, g, b
		s /= 100;
		l /= 100;
	if (s == 0)
		r = g = b = (l * 255);
	else {
		if (l <= 0.5)
			m2 = l * (s + 1);
		else
			m2 = l + s - l * s;
			m1 = l * 2 - m2;
			hue = h / 360;
			r = huetorgb(m1, m2, hue + 1/3);
			g = huetorgb(m1, m2, hue);
			b = huetorgb(m1, m2, hue - 1/3);
	}
	return "rgb(" + Math.round(r) + "," + Math.round(g) + "," + Math.round(b) + ")";
}

function getColorWithOffsets(h, s, l, o) {
	ho = so = lo = 0;
	if (o) {
		if (o.h) {
			ho = o.h;
		}
		if (o.s) {
			so = o.s;
		}
		if (o.l) {
			lo = o.l;
		}
	}
	ho = Math.max(-360, Math.min(360, (h+ho)));
	so = Math.max(0, Math.min(100, (s+so)));
	lo = Math.max(0, Math.min(100, (l+lo)));
	
	return hsl2rgb(ho, so, lo);
}

function updateColors(value, saturation, brightness) {
	var hue = Math.round((value/100)*360); // work out the hue from the slider value
		
	$("#saturation").css({"background-color" : hsl2rgb(hue, 100, 50)}); // change the saturation slider's background color
	
	var tmpTransforms = "";
	
	if ($.browser.msie) { // *sigh*
		$.each(rotColShiftOpts.cssTransforms, function(i, ttrans) {
			newColor = getColorWithOffsets(hue, saturation, brightness, ttrans.offsets);
			var tstyles = "";
			$.each(ttrans.attributes, function(i, ts) {
				tstyles += ts + ": " + newColor + ";";
			});
			tmpTransforms += ttrans.selector + "{ " + tstyles + " } ";
		});
		ieStyle.cssText = tmpTransforms;
	}
	else {		
		$.each(rotColShiftOpts.cssTransforms, function(i, ttrans) {
			newColor = getColorWithOffsets(hue, saturation, brightness, ttrans.offsets);
			var tstyles = "";
			$.each(ttrans.attributes, function(i, ts) {
				tstyles += ts + ": " + newColor + ";";
			});
			tmpTransforms += ttrans.selector + "{ " + tstyles + " } ";
		});
		
		$("style[title='colshift']").text(tmpTransforms);
	}
}

// and now the jquery...

$(document).ready(function() {
	if ($.browser.msie) {
		ieStyle = document.createStyleSheet();
	}
	else {		
		$("head").append('<style type="text/css" title="colshift"></style>');
	}
	
	// check for existing user settings
	if (rotColShiftOpts.useCookies) {
		if ($.cookies.get('rotates_hue')) { 
			rotColShiftOpts.hsl.h = Number($.cookies.get('rotates_hue'));
		}
		if ($.cookies.get('rotates_saturation')) { 
			rotColShiftOpts.hsl.s = Number($.cookies.get('rotates_saturation'));
		}
		if ($.cookies.get('rotates_brightness')) { 
			rotColShiftOpts.hsl.l = Number($.cookies.get('rotates_brightness'));
		}
	}
	// show the colour sliders
	$("#pickers").show();
	
	// set the sliders up and handle their input
	$("#colorpicker").slider({value: rotColShiftOpts.hsl.h, animate: rotColShiftOpts.sliderAnimSpeed}).bind('slide', function(event, ui) {
		rotColShiftOpts.hsl.h = Number(ui.value);
		updateColors(rotColShiftOpts.hsl.h, rotColShiftOpts.hsl.s, rotColShiftOpts.hsl.l);
	});
	$("#saturationpicker").slider({value: rotColShiftOpts.hsl.s, animate: rotColShiftOpts.sliderAnimSpeed}).bind('slide', function(event, ui) {
		rotColShiftOpts.hsl.s = Number(ui.value);
		updateColors(rotColShiftOpts.hsl.h, rotColShiftOpts.hsl.s, rotColShiftOpts.hsl.l);
	});
	$("#brightnesspicker").slider({value: rotColShiftOpts.hsl.l, animate: rotColShiftOpts.sliderAnimSpeed}).bind('slide', function(event, ui) {
		rotColShiftOpts.hsl.l = Number(ui.value);
		updateColors(rotColShiftOpts.hsl.h, rotColShiftOpts.hsl.s, rotColShiftOpts.hsl.l);
	});
	
	// more handlers (slidechange isn't updated on the fly so you're not trying to set cookies like 1000 times a second or something)
	$("#colorpicker").slider().bind('slidechange', function(event, ui) {
		rotColShiftOpts.hsl.h = Number(ui.value);
		setCookies(rotColShiftOpts.hsl.h, rotColShiftOpts.hsl.s, rotColShiftOpts.hsl.l);
	});
	$("#saturationpicker").slider().bind('slidechange', function(event, ui) {
		rotColShiftOpts.hsl.s = Number(ui.value);
		setCookies(rotColShiftOpts.hsl.h, rotColShiftOpts.hsl.s, rotColShiftOpts.hsl.l);
	});
	$("#brightnesspicker").slider().bind('slidechange', function(event, ui) {
		rotColShiftOpts.hsl.l = Number(ui.value);
		setCookies(rotColShiftOpts.hsl.h, rotColShiftOpts.hsl.s, rotColShiftOpts.hsl.l);
		
	});
	updateColors(rotColShiftOpts.hsl.h, rotColShiftOpts.hsl.s, rotColShiftOpts.hsl.l); // update the colours using defaults or cookie-retrieved values
});