import { RGB,HSL,HSV } from '../../types/color.uts';
import { bound01, pad2 } from './util';


/**
 * Handle bounds / percentage checking to conform to CSS color spec
 * 处理边界/百分比检查以符合 CSS 颜色规范
 * <http://www.w3.org/TR/css3-color/>
 * *Assumes:* r, g, b in [0, 255] or [0, 1]
 * *Returns:* { r, g, b } in [0, 255]
 */
function rgbToRgb(r: string, g: string, b: string):RGB;
function rgbToRgb(r: number, g: string, b: string):RGB;
function rgbToRgb(r: number, g: number, b: string):RGB;
function rgbToRgb(r: number, g: number, b: number):RGB;
function rgbToRgb(r: any,    g: any,    b: any) : RGB {
	return {
		r: bound01(r, 255) * 255,
		g: bound01(g, 255) * 255,
		b: bound01(b, 255) * 255,
	} as RGB;
}
export {
	rgbToRgb
}
/**
 * Converts an RGB color value to HSL.
 * 将 RGB 颜色值转换为 HSL。
 * *Assumes:* r, g, and b are contained in [0, 255] or [0, 1]
 * *Returns:* { h, s, l } in [0,1]
 */
function rgbToHsl(r: string, g: string, b: string):HSL;
function rgbToHsl(r: number, g: string, b: string):HSL;
function rgbToHsl(r: number, g: number, b: string):HSL;
function rgbToHsl(r: number, g: number, b: number):HSL;
function rgbToHsl(r : any, g : any, b : any) : HSL {
	r = bound01(r, 255);
	g = bound01(g, 255);
	b = bound01(b, 255);

	const max = Math.max(r, g, b);
	const min = Math.min(r, g, b);
	let h = 0;
	let s:number// = 0;
	const l = (max + min) / 2;

	if (max == min) {
		s = 0;
		h = 0; // achromatic
	} else {
		const d = max - min;
		s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
		switch (max) {
			case r:
				h = (g - b) / d + (g < b ? 6 : 0);
				break;
			case g:
				h = (b - r) / d + 2;
				break;
			case b:
				h = (r - g) / d + 4;
				break;
			default:
				console.log('h')
				break;
		}

		h /= 6;
	}

	return { h, s, l } as HSL;
}

export {
	rgbToHsl
}

export function hue2rgb(p : number, q : number, t : number) : number {
	let _t = t
	if (_t < 0) {
		_t += 1;
	}

	if (_t > 1) {
		_t -= 1;
	}

	if (_t < 1 / 6) {
		return p + (q - p) * (6 * _t);
	}

	if (_t < 1 / 2) {
		return q;
	}

	if (_t < 2 / 3) {
		return p + (q - p) * (2 / 3 - _t) * 6;
	}

	return p;
}

/**
 * Converts an HSL color value to RGB.
 * 将 HSL 颜色值转换为 RGB。
 * *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100]
 * *Returns:* { r, g, b } in the set [0, 255]
 */ 
function hslToRgb(h : string,s : string,l : string) : RGB 
function hslToRgb(h : number,s : string,l : string) : RGB 
function hslToRgb(h : number,s : number,l : string) : RGB 
function hslToRgb(h : number,s : number,l : number) : RGB 
function hslToRgb(h : any,s : any,l : any) : RGB {
	let r : number;
	let g : number;
	let b : number;
	h = bound01(h, 360);
	s = bound01(s, 100);
	l = bound01(l, 100);
	
	if (s == 0) {
		// achromatic
		g = l;
		b = l;
		r = l;
	} else {
		const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
		const p = 2 * l - q;
		r = hue2rgb(p, q, h + 1 / 3);
		g = hue2rgb(p, q, h);
		b = hue2rgb(p, q, h - 1 / 3);
	}

	return { r: r * 255, g: g * 255, b: b * 255 } as RGB;
}
export {
	hslToRgb
}
/**
 * Converts an RGB color value to HSV
 * 将RGB颜色值转换为HSV颜色值
 * *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1]
 * *Returns:* { h, s, v } in [0,1]
 */
export function rgbToHsv(r : number, g : number, b : number) : HSV {
	r = bound01(r, 255);
	g = bound01(g, 255);
	b = bound01(b, 255);

	const max = Math.max(r, g, b);
	const min = Math.min(r, g, b);
	let h = 0;
	const v = max;
	const d = max - min;
	const s = max == 0 ? 0 : d / max;

	if (max == min) {
		h = 0; // achromatic
	} else {
		switch (max) {
			case r:
				h = (g - b) / d + (g < b ? 6 : 0);
				break;
			case g:
				h = (b - r) / d + 2;
				break;
			case b:
				h = (r - g) / d + 4;
				break;
			default:
				console.log('1')
				break;
		}

		h /= 6;
	}

	return { h, s, v } as HSV;
}

/**
 * Converts an HSV color value to RGB.
 * 将HSV颜色值转换为RGB。
 * *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100]
 * *Returns:* { r, g, b } in the set [0, 255]
 */
function hsvToRgb( h : string, s : string, v : string) : RGB 
function hsvToRgb( h : number, s : string, v : string) : RGB 
function hsvToRgb( h : number, s : number, v : string) : RGB 
function hsvToRgb( h : number, s : number, v : number) : RGB 
function hsvToRgb( h : any, s : any, v : any) : RGB {
	h = bound01(h, 360) * 6;
	s = bound01(s, 100);
	v = bound01(v, 100);

	const i = Math.floor(h);
	const f = h - i;
	const p = v * (1 - s);
	const q = v * (1 - f * s);
	const t = v * (1 - (1 - f) * s);
	const mod = i % 6;
	const r = [v, q, p, p, t, v][mod];
	const g = [t, v, v, q, p, p][mod];
	const b = [p, p, t, v, v, q][mod];

	return { r: r * 255, g: g * 255, b: b * 255 } as RGB;
}
export {
	hsvToRgb
}
/**
 * Converts an RGB color to hex
 * 将RGB颜色转换为十六进制。
 * Assumes r, g, and b are contained in the set [0, 255]
 * Returns a 3 or 6 character hex
 */
export function rgbToHex(r : number, g : number, b : number, allow3Char : boolean = false) : string {
	const hex = [
		pad2(Math.round(r).toString(16)),
		pad2(Math.round(g).toString(16)),
		pad2(Math.round(b).toString(16)),
	];

	// Return a 3 character hex if possible
	if (
		allow3Char &&
		hex[0].startsWith(hex[0].charAt(1)) &&
		hex[1].startsWith(hex[1].charAt(1)) &&
		hex[2].startsWith(hex[2].charAt(1))
	) {
		return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0);
	}

	return hex.join('');
}

/**
 * Converts an RGBA color plus alpha transparency to hex
 * 将带有透明度的RGBA颜色转换为十六进制。
 * Assumes r, g, b are contained in the set [0, 255] and
 * a in [0, 1]. Returns a 4 or 8 character rgba hex
 */
// eslint-disable-next-line max-params
export function rgbaToHex(r : number, g : number, b : number, a : number, allow4Char : boolean = false) : string {
	const hex = [
		pad2(Math.round(r).toString(16)),
		pad2(Math.round(g).toString(16)),
		pad2(Math.round(b).toString(16)),
		pad2(convertDecimalToHex(a)),
	];

	// Return a 4 character hex if possible
	if (
		allow4Char &&
		hex[0].startsWith(hex[0].charAt(1)) &&
		hex[1].startsWith(hex[1].charAt(1)) &&
		hex[2].startsWith(hex[2].charAt(1)) &&
		hex[3].startsWith(hex[3].charAt(1))
	) {
		return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0) + hex[3].charAt(0);
	}

	return hex.join('');
}

/**
 * Converts an RGBA color to an ARGB Hex8 string
 * 将RGBA颜色转换为ARGB十六进制字符串。
 * Rarely used, but required for "toFilter()"
 */
export function rgbaToArgbHex(r : number, g : number, b : number, a : number) : string {
	const hex = [
		pad2(convertDecimalToHex(a)),
		pad2(Math.round(r).toString(16)),
		pad2(Math.round(g).toString(16)),
		pad2(Math.round(b).toString(16)),
	];

	return hex.join('');
}

/** Converts a decimal to a hex value */
/** 将十进制转换为十六进制值。 */
function convertDecimalToHex(d : number) : string
function convertDecimalToHex(d : string) : string
function convertDecimalToHex(d : any) : string {
	return Math.round(parseFloat(`${d}`) * 255).toString(16);
}
export {convertDecimalToHex}
/** Converts a hex value to a decimal */
export function convertHexToDecimal(h : string) : number {
	return parseIntFromHex(h) / 255;
}

/** Parse a base-16 hex value into a base-10 integer */
export function parseIntFromHex(val : string) : number {
	return parseInt(val, 16);
}

export function numberInputToObject(color : number) : RGB {
	return {
		r: color >> 16,
		g: (color & 0xff00) >> 8,
		b: color & 0xff,
	} as RGB;
}