/**COLOR: convertors, comparators
 *@author danyastuff
 */

Number.prototype.fromPercent = function (base) {return base / 100 * this }
Number.prototype.toPercent   = function (base) {return this / base * 100 }
Number.prototype.round		 = function ()	   {return Math.round(this)  } 

var H_BASE   = 360,
	SV_BASE  = 100,
	RGB_BASE = 255;

COLOR = {
//CONVERTORS	
	hsv2rgb : function (hsv) {
		var h = hsv.h, s = hsv.s, v = hsv.v;
		
		while(h >= H_BASE) h -= H_BASE;
		
		h /= H_BASE/6;
		s /= SV_BASE;
		v /= SV_BASE;
		
		var m, n, 
			i = Math.floor(h),
			f = h - i
									
		if ( !(i & 1) ) f = 1 - f; // if i is even
		
		m = v * (1 - s);
		n = v * (1 - s * f);
		
		v = Math.round(v * RGB_BASE);
		n = Math.round(n * RGB_BASE);
		m = Math.round(m * RGB_BASE);
		
		switch (i) {
			case 0: return {r:v, g:n, b:m};
			case 1: return {r:n, g:v, b:m};
			case 2: return {r:m, g:v, b:n};
			case 3: return {r:m, g:n, b:v};
			case 4: return {r:n, g:m, b:v};
			case 5: return {r:v, g:m, b:n};
		} 
	},
	rgb2hsv : function (rgb) {
		var r = rgb.r, g = rgb.g, b = rgb.b;
		
		var dmax, minc, maxc, hsv = {h:0, s:0, v:0};
			
		maxc = (r > g) ? ((r > b) ? r : b) : ((g > b)? g : b);
		minc = (r < g) ? ((r < b) ? r : b) : ((g < b)? g : b);
		
		hsv.s = 0;
		
		if (maxc) hsv.s = (maxc - minc) * RGB_BASE / maxc;
			
		hsv.v = maxc;
		
		if (!hsv.s) 
		{
			hsv.h = 0;
		} else { 
			dmax = maxc - minc;
			rc = (maxc - r) / dmax;
			gc = (maxc - g) / dmax;
			bc = (maxc - b) / dmax;
			
			if (r == maxc)
				hsv.h = bc - gc;
			else if (g == maxc)
				hsv.h = 2 + rc - bc;
			else
				hsv.h = 4 + gc - rc;
				
			hsv.h *= H_BASE/6;
			
			if (hsv.h < 0) hsv.h += H_BASE;
			if (hsv.h == H_BASE) hsv.h = 0;
		}
		
		hsv.h = Math.round(hsv.h);
		hsv.s = Math.round(hsv.s / RGB_BASE * SV_BASE);
		hsv.v = Math.round(hsv.v / RGB_BASE * SV_BASE);
		
		return hsv;
	},
	rgb2css : function (rgb) {
		return ((rgb.r << 16) + (rgb.g << 8) + rgb.b + 0xF000000).toString(16).substr(1, 8).toUpperCase()
	},
	css2rgb : function (css) {
		if (typeof css == 'string')
		{
			css = css.replace('#','').replace('0x','');
			hex = parseInt(css, 16);
		} else {
			hex = css;
		}
		return {
			r:  hex >> 16,
			g: (hex & 0x00FF00) >> 8,
			b:  hex & 0x0000FF
		}
	},
	rgb2cmyk : function (rgb) {
		var c = 1 - rgb.r / 255,
			m = 1 - rgb.g / 255,
			y = 1 - rgb.b / 255,
			k = Math.min(c, m, y)
		
		if (k == 1) 
			c = m = y = 0;
		else {
			c = (c - k) / (1 - k) *100;
			m = (m - k) / (1 - k) *100;
			y = (y - k) / (1 - k) *100;
		}
		k *= 100

		return {
			c: Math.floor(c), 
			m: Math.floor(m), 
			y: Math.floor(y), 
			k: Math.floor(k)
		}
	},
	cmyk2rgb : function (cmyk) {
		var c = cmyk.c, m = cmyk.m, y = cmyk.y, k = cmyk.k;    
		c /=100, m /=100, y /=100, k /=100;
		return {
			r: Math.floor( (1 - c * (1 - k) - k) *255 ), 
			g: Math.floor( (1 - m * (1 - k) - k) *255 ), 
			b: Math.floor( (1 - y * (1 - k) - k) *255 ) 
		}; 
	},	

//COMPARATORS
	
 	// color difference
	clrDiff : function (c1, c2) { //RGB
		var diff = 	Math.max(c1.r, c2.r) - Math.min(c1.r, c2.r) +
			   		Math.max(c1.g, c2.g) - Math.min(c1.g, c2.g) +
			   		Math.max(c1.b, c2.b) - Math.min(c1.b, c2.b);
		return Math.round(100 - diff / 765 * 100)
	},
	
 	// Pythagorean Distance
	distance : function (c1, c2) {
		var rd = c1.r - c2.r, 
			gd = c1.g - c2.g, 
			bd = c1.b - c2.b
		return Math.sqrt( rd*rd + gd*gd + bd*bd )
	},
	
 	// brightness difference
	briDiff : function (c1, c2) {
		return Math.round( 
			Math.abs(COLOR.bright(c1) - COLOR.bright(c2)) / 255 * 100
		)
	},

 	// Luminisity conrast (must be > 5)
	contrast : function (c1, c2) {
		var l1 = COLOR.lumin(c1),
			l2 = COLOR.lumin(c2);
		
		var con = l1 < l2 
			? 1 - (l1 + 0.05) / (l2 + 0.05)
			: 1 - (l2 + 0.05) / (l1 + 0.05);
		return Math.round(con * 100)
	},
	
 	// utils
	bright : function (c) {
		return (299*c.r + 587*c.g + 114*c.b) / 1000;
	},
	lumin : function (c) { // luminisity for RGB-color 
		return 0.2126 * Math.pow(c.r/255, 2.2) +
			   0.7152 * Math.pow(c.g/255, 2.2) +
			   0.0722 * Math.pow(c.b/255, 2.2); 
	}
 
}