// inicializace globalniho objektu se vsemi barevnymi slozkami a funkcemi pro vypocet/nastaveni hodnot techto slozek 
var basic = {};

function init() {

	var valr = document.getElementById('rgbrval'),
		valg = document.getElementById('rgbgval'),
		valb = document.getElementById('rgbbval'),
		sliderr = document.getElementById('sliderr'),
		sliderg = document.getElementById('sliderg'),
		sliderb = document.getElementById('sliderb'),

		valc = document.getElementById('cmycperc'),
		valm = document.getElementById('cmymperc'),
		valy = document.getElementById('cmyyperc'),
		sliderc = document.getElementById('sliderc'),
		sliderm = document.getElementById('sliderm'),
		slidery = document.getElementById('slidery'),

		valh = document.getElementById('hsbhval'),
		vals = document.getElementById('hsbsval'),
		vali = document.getElementById('hsbival'),
		sliderh = document.getElementById('sliderh'),
		sliders = document.getElementById('sliders'),
		slideri = document.getElementById('slideri'),

		valy2 = document.getElementById('ycbcryval'),
		valcb = document.getElementById('ycbcrcbval'),
		valcr = document.getElementById('ycbcrcrval'),
		slidery2 = document.getElementById('slidery2'),
		slidercb = document.getElementById('slidercb'),
		slidercr = document.getElementById('slidercr'),

		vall = document.getElementById('lablval'),
		vala = document.getElementById('labaval'),
		valb2 = document.getElementById('labb2val'),
		sliderl = document.getElementById('sliderl'),
		slidera = document.getElementById('slidera'),
		sliderb2 = document.getElementById('sliderb2');




	basic = {
		// vychozí hodnoty barevných složek
		r: 0,
		g: 0,
		b: 0,

		c: 0,
		m: 0,
		y: 0,

		h: 240,
		s: 100,
		i: 0,

		y2: 16,
		cb: 128,
		cr: 128,

		l: 0,
		a: 0,
		b2: 0,

		// Funkce pro nastaveni aktualnich barevnych hodnot (pri zmene polohy slideru) 
		setR: function (val) {
			if (isNaN(val)) return;
			this.r = Number(val);
			recalc(true);
			recalc({ hsi: true, ycbcr: true, lab: true });
		},
		setG: function (val) {
			if (isNaN(val)) return;
			this.g = Number(val);
			recalc(true);
			recalc({ hsi: true, ycbcr: true, lab: true });
		},
		setB: function (val) {
			if (isNaN(val)) return;
			this.b = Number(val);
			recalc(true);
			recalc({ hsi: true, ycbcr: true, lab: true });
		},
		setC: function (val) {
			if (isNaN(val)) return;
			this.r = 255 - val;
			recalc(true);
			recalc({ hsi: true, ycbcr: true, lab: true });
		},
		setM: function (val) {
			if (isNaN(val)) return;
			this.g = 255 - val;
			recalc(true);
			recalc({ hsi: true, ycbcr: true, lab: true });
		},
		setY: function (val) {
			if (isNaN(val)) return;
			this.b = 255 - val;
			recalc({ hsi: true, ycbcr: true, lab: true });
		},
		setH: function (val) {
			if (isNaN(val)) return;
			this.h = Number(val);
			HSItoRGB(basic);
			recalc({ hsi: false, ycbcr: true, lab: true });
		},
		setS: function (val) {
			if (isNaN(val)) return;
			this.s = Number(val);
			HSItoRGB(basic);
			recalc({ hsi: false, ycbcr: true, lab: true });
		},
		setI: function (val) {
			if (isNaN(val)) return;
			this.i = Number(val);
			HSItoRGB(basic);
			recalc({ hsi: false, ycbcr: true, lab: true });
		},
		setY2: function (val) {
			if (isNaN(val)) return;
			this.y2 = Number(val);
			YCbCrtoRGB(basic);
			recalc({ hsi: true, ycbcr: false, lab: true });
		},
		setCb: function (val) {
			if (isNaN(val)) return;
			this.cb = Number(val);
			YCbCrtoRGB(basic);
			recalc({ hsi: true, ycbcr: false, lab: true });
		},
		setCr: function (val) {
			if (isNaN(val)) return;
			this.cr = Number(val);
			YCbCrtoRGB(basic);
			recalc({ hsi: true, ycbcr: false, lab: true });
		},
		setL: function (val) {
			if (isNaN(val)) return;
			this.l = Number(val);
			LABtoRGB(basic);
			recalc({ hsi: true, ycbcr: true, lab: false });
		},
		setA: function (val) {
			if (isNaN(val)) return;
			this.a = Number(val);
			LABtoRGB(basic);
			recalc({ hsi: true, ycbcr: true, lab: false });
		},
		setB2: function (val) {
			if (isNaN(val)) return;
			this.b2 = Number(val);
			LABtoRGB(basic);
			recalc({ hsi: true, ycbcr: true, lab: false });
		}

	}




	function recalc(recalcType) { // funkce pro prepocet vsech barevnych slozek ve vsech modelech/prostorech 

		if (recalcType.lab) RGBtoLAB(basic);

		if (recalcType.ycbcr) RGBtoYCbCr(basic);

		if (recalcType.hsi) RGBtoHSI(basic);

		if (basic.r > 255) basic.r = 255;
		if (basic.g > 255) basic.g = 255;
		if (basic.b > 255) basic.b = 255;

		if (basic.r < 0) basic.r = 0;
		if (basic.g < 0) basic.g = 0;
		if (basic.b < 0) basic.b = 0;

		valr.value = basic.r;
		sliderr.value = basic.r;
		valg.value = basic.g;
		sliderb.value = basic.b;
		valb.value = basic.b;
		sliderg.value = basic.g;

		valc.value = Math.round((255 - basic.r));
		sliderc.value = 255 - basic.r;
		valm.value = Math.round((255 - basic.g));
		sliderm.value = 255 - basic.g;
		valy.value = Math.round((255 - basic.b));
		slidery.value = 255 - basic.b;

		if (basic.h > 360) basic.h = 360;
		if (basic.s > 100) basic.s = 100;
		if (basic.i > 100) basic.i = 100;

		if (basic.h < 0) basic.h = 0;
		if (basic.s < 0) basic.s = 0;
		if (basic.i < 0) basic.i = 0;

		valh.value = basic.h;
		sliderh.value = basic.h;
		vals.value = basic.s;
		sliders.value = basic.s;
		vali.value = basic.i;
		slideri.value = basic.i;

		if (basic.y2 > 235) basic.y2 = 235;
		if (basic.cb > 240) basic.cb = 240;
		if (basic.cr > 240) basic.cr = 240;

		//if (basic.y2 > 0 || basic.y2 < 16) basic.y2 = 16;
		//if (basic.cb < 0) basic.cb = 16;
		//if (basic.cr < 0) basic.cr = 16;

		valy2.value = basic.y2;
		slidery2.value = basic.y2;
		valcb.value = basic.cb;
		slidercb.value = basic.cb;
		valcr.value = basic.cr;
		slidercr.value = basic.cr;



		if (basic.l > 100) basic.l = 100;
		if (basic.a > 128) basic.a = 128;
		if (basic.b2 > 128) basic.b2 = 128;

		if (basic.l < 0) basic.l = 0;
		if (basic.a < -128) basic.a = -128;
		if (basic.b2 < -128) basic.b2 = -128;

		vall.value = basic.l;
		sliderl.value = basic.l;
		vala.value = basic.a;
		slidera.value = basic.a;
		valb2.value = basic.b2;
		sliderb2.value = basic.b2;


		document.getElementById("outer-div").style.backgroundColor = rgb2hex(basic.r, basic.g, basic.b);
		document.getElementById('inner-div').style.backgroundColor = rgb2hex(255 - basic.r, 255 - basic.g, 255 - basic.b);
	}
}

setTimeout(init, 100);

//Pomocne funkce pro prepocet slozek RGB do modelu HSI, LAB, YCbCr

//Převzato z ttps://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb
function rgb2hex(red, green, blue) { // RGB to HEX 
	var rgb = blue | (green << 8) | (red << 16);
	return '#' + (0x1000000 + rgb).toString(16).slice(1)
}

function HSItoRGB(basic) { // převod HSI na RGB

	var h = basic.h,
		s = basic.s / 100,
		i = basic.i / 100,

		r, g, b;

	if (s === 0) {
		r = 1;
		g = 1;
		b = 1;
	} if (h < 120) {
		b = (1 - s) / 3;
		r = (1 + s * Math.cos(h * Math.PI / 180) / Math.cos(Math.PI / 3 - h * Math.PI / 180)) / 3;
		g = 1 - r - b;
	} else if (h < 240) {
		h -= 120;
		r = (1 - s) / 3;
		g = (1 + s * Math.cos(h * Math.PI / 180) / Math.cos(Math.PI / 3 - h * Math.PI / 180)) / 3;
		b = 1 - r - g;
	} else {
		h -= 240;
		g = (1 - s) / 3;
		b = (1 + s * Math.cos(h * Math.PI / 180) / Math.cos(Math.PI / 3 - h * Math.PI / 180)) / 3;
		r = 1 - b - g;
	}

	basic.r = Math.round(i * r * 3 * 255);
	basic.g = Math.round(i * g * 3 * 255);
	basic.b = Math.round(i * b * 3 * 255);
}

function RGBtoHSI(basic) {// převod RGB na HSI
	var r = basic.r / 255,
		g = basic.g / 255,
		b = basic.b / 255;



	basic.i = Math.round((r + g + b) * 100 / 3);

	if (r === g && g === b) {
		basic.s = basic.h = 0;
	} else {
		basic.s = Math.round((1 - 3 * Math.min(r, g, b) / (r + g + b)) * 100);

		var w = 0.5 * (r - g + r - b) / Math.sqrt((r - g) * (r - g) + (r - b) * (g - b));
		// osetreni cos
		if (w > 1) w = 1;
		if (w < -1) w = -1;

		basic.h = Math.round(Math.acos(w) / Math.PI * 180);

		if (b > g) basic.h = 360 - basic.h;
	}
}

function YCbCrtoRGB(basic) {// převod YCbCr na  RGB

	var y = basic.y2 / 255,
		cb = basic.cb / 255,
		cr = basic.cr / 255,

		r, g, b;

	r = 298.082 * y + 408.583 * cr - 222.921;
	g = 298.082 * y - 100.291 * cb - 208.12 * cr + 135.576;
	b = 298.082 * y + 516.412 * cb - 276.836;

	/* r = 1.164*(y-16) + 1.596*(cr-128)
	g = 1.164*(y-16) - 0.813*(cr-128) - 0.392*(cb-128)
	b = 1.164*(y-16) + 2.017*(cb-128)*/

	basic.r = Math.round(r);
	basic.g = Math.round(g);
	basic.b = Math.round(b);

}

function RGBtoYCbCr(basic) { // převod RGB na YCbCr
	var r = basic.r / 255,
		g = basic.g / 255,
		b = basic.b / 255,

		y, cb, cr;
	/*y = 0.257*r + 0.504*g + 0.098*b + 16
	cb = -0.148*r - 0.291*g + 0.439*b + 128
	cr = 0.439*r - 0.368*g - 0.071*b + 128*/
	y = 16 + 65.481 * r + 128.553 * g + 24.966 * b;
	cb = 128 - 37.797 * r - 74.203 * g + 112 * b;
	cr = 128 + 112 * r - 93.786 * g - 18.214 * b;

	basic.y2 = Math.round(y);
	basic.cb = Math.round(cb);
	basic.cr = Math.round(cr);

}

function LABtoRGB(basic) {// převod  Lab na RGB

	var l = basic.l,
		a = basic.a,
		b2 = basic.b2,

		x, y, z, r, g, b;

	fy = (l + 16) / 116;
	y = fy > 6 / 29 ? Math.pow(fy, 3) * 255 : (fy - 16 / 116) * 3 * 0.042806 * 255;
	fx = fy + a / 500;
	x = fx > 6 / 29 ? Math.pow(fx, 3) * 255 : (fx - 16 / 116) * 3 * 0.042806 * 255;
	fz = fy - b2 / 200;
	z = fz > 6 / 29 ? Math.pow(fz, 3) * 255 : (fz - 16 / 116) * 3 * 0.042806 * 255;

	/*	//CIE RGB
		r = 2.3706743     * x -0.9000405    * y -0.4706338 * z; 
		g = -0.5138850    * x + 1.4253036  * y + 0.0885814 * z; 
		b = 0.0052982 * x -0.0146949* y + 1.0093968 * z; */
	//Hodnoty transformační matice M byly převzaty z http://www.brucelindbloom.com/ pro prostor sRGB
	//sRGB
	r = 3.2404542 * x - 1.5371385 * y - 0.4985314 * z;
	g = -0.9692660 * x + 1.8760108 * y + 0.0415560 * z;
	b = 0.0556434 * x - 0.2040259 * y + 1.0572252 * z;

	basic.r = Math.round(r);
	basic.g = Math.round(g);
	basic.b = Math.round(b);
}

function RGBtoLAB(basic) { // převod RGB na Lab
	var r = basic.r / 255,
		g = basic.g / 255,
		b = basic.b / 255,

		x, y, z, fx, fy, fz, l, a, b2;

	//sRGB
	x = 0.4124564 * r + 0.3575761 * g + 0.1804375 * b;
	fx = fXYZ(x);
	y = 0.2126729 * r + 0.7151522 * g + 0.0721750 * b;
	fy = fXYZ(y);
	z = 0.0193339 * r + 0.1191920 * g + 0.9503041 * b;
	fz = fXYZ(z);

	//CIE RGB
	/*x = 0.4887180    * r +0.3106803    * g + 0.2006017 * b; 
	fx = fXYZ(x);
	y = 0.1762044    * r + 0.8129847  * g + 0.0108109 * b; 
	fy = fXYZ(y);
	z = 0.0102048  * g + 0.9897952 * b; 
	fz = fXYZ(z);*/

	l = 116 * fy - 16;
	a = 500 * (fx - fy);
	b2 = 200 * (fy - fz)

	basic.l = Math.round(l);
	basic.a = Math.round(a);
	basic.b2 = Math.round(b2);
}

function fXYZ(value) {
	if (value > 0.008856) {

		return Math.cbrt(value);
	} else {
		return 7.787037 * value + 0.137931;
		// return (903.3 * value + 16) / 116;
	}
}
