using UnityEngine;
using System.Collections;

public struct ColorHsv 
{
	static public string[] hueNames = new string[]
	{"Red", "Scarlet", "Vermilion", "Tangelo", "Orange", "Gamboge", "Amber", "Gold",
		"Yellow", "Apple", "Lime", "Spring", "Chartreuse", "Pistachio", "Harlequin", "Sap",
		"Green", "Emerald", "Malachite", "Sea", "Spring", "Aquamarine", "Turquoise", "Opal",
		"Cyan", "Arctic", "Cerulean", "Cornflower", "Azure", "Cobalt", "Sapphire", "Phthalo",
		"Blue", "Persian", "Indigo", "Blue Violet", "Violet", "Purple", "Mulberry", "Heliotrope",
		"Magenta", "Orchid", "Fuchsia", "Cerise", "Rose", "Raspberry", "Crimson", "Amaranth"};
	
	public float h;
	public float s;
	public float v;
	public float a;
	
	public ColorHsv(float h, float s, float v, float a)
	{
		this.h = h;
		this.s = s;
		this.v = v;
		this.a = a;
	}
	
	public ColorHsv(float h, float s, float v) : this(h, s, v, 1f)
	{		
	}
	
	public ColorHsv(Color colorRgb)
	{
		a = colorRgb.a;
		var max = Mathf.Max(colorRgb.r, colorRgb.g, colorRgb.b);
		var min = Mathf.Min(colorRgb.r, colorRgb.g, colorRgb.b);
		var d = max - min;
		h = 0f;
		s = max == 0f ? 0f : d / max;
		v = max;

		if (max != min)
		{
			h = ColorExtensions.GetHue(colorRgb.r, colorRgb.g, colorRgb.b, max, d);
		}
	}
	
	public ColorHsv(Color32 colorRgb) : this((Color)colorRgb)
	{
	}
	
	public static implicit operator Color(ColorHsv value)
	{
		return value.ToColor();
	}
	
	public static implicit operator Color32(ColorHsv value)
	{
		return value.ToColor32();
	}
	
	public static implicit operator ColorHsv(Color value)
	{
		return new ColorHsv(value);
	}
	
	public static implicit operator ColorHsv(Color32 value)
	{
		return new ColorHsv(value);
	}
	
	public Color ToColor()
	{
		float r = 0f;
		float g = 0f;
		float b = 0f;
		
		var i = Mathf.FloorToInt(h * 6f);
		var f = h * 6f - i;
		var p = v * (1f - s);
		var q = v * (1f - f * s);
		var t = v * (1f - (1f - f) * s);
		
		switch(i % 6)
		{
			case 0:
				r = v;
				g = t;
				b = p;
				break;
			case 1:
				r = q;
				g = v;
				b = p;
				break;
			case 2:
				r = p;
				g = v;
				b = t;
				break;
			case 3:
				r = p;
				g = q;
				b = v;
				break;
			case 4:
				r = t;
				g = p;
				b = v;
				break;
			case 5:
				r = v;
				g = p;
				b = q;
				break;
		}
		
		return new Color(r, g, b, a);
	}
	
	public Color32 ToColor32()
	{
		return ToColor();
	}
	
	public string GetName()
	{
		if(s > 0f && v > 0f)
		{
			var hue = h * 48f;
			var hueIndex = ((int)hue);
			var hueRemain = hue - (float)hueIndex;
			
			if(hueRemain > 0.5f)
			{
				hueIndex++;
				if(hueIndex >= 48)
				{
					hueIndex = 0;
				}
				hueRemain -= 1f;
			}
			
			return hueNames[hueIndex] 
			+ (hueRemain * 450f).ToString(" +#; -#;") 
			+ (s < 1f ? s.ToString(" :#%") : "")
			+ (s < 1f || v < 1f ? v.ToString(" :#%") : "");
		}
		else
		{
			if(v.Approximately(1f))
			{
				return "White";				
			}
			if(v.Approximately(0f))
			{
				return "Black";				
			}
			
			return "Grey " + v.ToString(" :#%");
		}
	}
	
}
