<?php 

namespace Primal\Color;

class Parser {
	
	protected $chunks;
	protected $result;


	function __construct($input) {
		
		if ($input instanceof Color) {
			$this->result = $input;
			return;
		}
		
		//first see if it's a named color. if it is, set our result and end there.
		if (($result = static::GetNamedColor($input)) !== false) {
			$this->result = $result;
			return;
		}
		
		//see if we have a pattern to match the input, throw an exception
		if (($type = $this->findPattern($input)) === false) {
			throw new UnknownFormatException("Color did not match any available patterns.");
		}
		
		$this->type = $type;
		
		if (is_callable(array($this, $type))) {
			$this->$type();
		} else {
			throw new ParserException("Input was matched to type $type, but no matching parser function was found.");
		}
		
	}
	
	function getResult() {
		return $this->result;
	}
	
	static function Parse($input) {
		$self = new static($input);
		return $self->getResult();
	}
	
	protected function findPattern($input) {
		foreach (static::$patterns as $type=>$pattern) {
			$chunks = array();
			if (preg_match($pattern, $input, $chunks)) {
				$this->chunks = $chunks;
				return $type;
			}
		}
		return false;
	}
	
	
	protected static function GetNamedColor($input) {
		$input = strtolower($input);
		if (!isset(static::$named_colors[$input])) {
			return false;
		}
		
		$chunks = array();
		if (preg_match(static::$patterns['hex6'], static::$named_colors[$input], $chunks)) {
			return new RGBColor(hexdec($chunks[1]), hexdec($chunks[2]), hexdec($chunks[3]));
		}
		
		return false;
	}

	
	//parser functions
	function cmyk () {$this->result = new CMYKColor((float)$this->chunks[1] * 100, (float)$this->chunks[2] * 100, (float)$this->chunks[3] * 100, (float)$this->chunks[4] * 100);}
	function rgba () {$this->result = new RGBColor((int)$this->chunks[1], (int)$this->chunks[2], (int)$this->chunks[3], (float)$this->chunks[4]);}
	function rgb  () {$this->result = new RGBColor((int)$this->chunks[1], (int)$this->chunks[2], (int)$this->chunks[3]);}
	function hsla () {$this->result = new HSLColor((int)$this->chunks[1], (int)$this->chunks[2], (int)$this->chunks[3], (float)$this->chunks[4]);}
	function hsl  () {$this->result = new HSLColor((int)$this->chunks[1], (int)$this->chunks[2], (int)$this->chunks[3]);}
	function hsva () {$this->result = new HSVColor((int)$this->chunks[1], (int)$this->chunks[2], (int)$this->chunks[3], (float)$this->chunks[4]);}
	function hsv  () {$this->result = new HSVColor((int)$this->chunks[1], (int)$this->chunks[2], (int)$this->chunks[3]);}
	function hex6 () {$this->result = new RGBColor(hexdec($this->chunks[1]), hexdec($this->chunks[2]), hexdec($this->chunks[3]));}
	function hex3 () {$this->result = new RGBColor(hexdec($this->chunks[1])*16, hexdec($this->chunks[2])*16, hexdec($this->chunks[3])*16);}

	
	static $patterns = array(
		'cmyk'  => '/^(?:device-)?cmyk\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3}),\s*(\d+(?:\.\d+)?|\.\d+)\s*\)/',
		'rgba'  => '/^rgba\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3}),\s*(\d+(?:\.\d+)?|\.\d+)\s*\)/',
		'rgb'   => '/^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/',
		'hsla'  => '/^hsla\((\d{1,3}),\s*(\d{1,3})%,\s*(\d{1,3})%,\s*(\d+(?:\.\d+)?|\.\d+)\s*\)/',
		'hsl'   => '/^hsl\((\d{1,3}),\s*(\d{1,3})%,\s*(\d{1,3})%\)$/',
		'hsva'  => '/^hsva\((\d{1,3}),\s*(\d{1,3})%,\s*(\d{1,3})%,\s*(\d+(?:\.\d+)?|\.\d+)\s*\)$/',
		'hsv'   => '/^hsv\((\d{1,3}),\s*(\d{1,3})%,\s*(\d{1,3})%\)$/',
		'hex6'  => '/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/',
		'hex3'  => '/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/'
	);

	static $named_colors = array(
		"aliceblue"			   => "f0f8ff",
		"antiquewhite"		   => "faebd7",
		"aqua"				   => "00ffff",
		"aquamarine"		   => "7fffd4",
		"azure"				   => "f0ffff",
		"beige"				   => "f5f5dc",
		"bisque"			   => "ffe4c4",
		"black"				   => "000000",
		"blanchedalmond"	   => "ffebcd",
		"blue"				   => "0000ff",
		"blueviolet"		   => "8a2be2",
		"brown"				   => "a52a2a",
		"burlywood"			   => "deb887",
		"cadetblue"			   => "5f9ea0",
		"chartreuse"		   => "7fff00",
		"chocolate"			   => "d2691e",
		"coral"				   => "ff7f50",
		"cornflowerblue"	   => "6495ed",
		"cornsilk"			   => "fff8dc",
		"crimson"			   => "dc143c",
		"cyan"				   => "00ffff",
		"darkblue"			   => "00008b",
		"darkcyan"			   => "008b8b",
		"darkgoldenrod"		   => "b8860b",
		"darkgray"			   => "a9a9a9",
		"darkgreen"			   => "006400",
		"darkkhaki"			   => "bdb76b",
		"darkmagenta"		   => "8b008b",
		"darkolivegreen"	   => "556b2f",
		"darkorange"		   => "ff8c00",
		"darkorchid"		   => "9932cc",
		"darkred"			   => "8b0000",
		"darksalmon"		   => "e9967a",
		"darkseagreen"		   => "8fbc8f",
		"darkslateblue"		   => "483d8b",
		"darkslategray"		   => "2f4f4f",
		"darkturquoise"		   => "00ced1",
		"darkviolet"		   => "9400d3",
		"deeppink"			   => "ff1493",
		"deepskyblue"		   => "00bfff",
		"dimgray"			   => "696969",
		"dodgerblue"		   => "1e90ff",
		"feldspar"			   => "d19275",
		"firebrick"			   => "b22222",
		"floralwhite"		   => "fffaf0",
		"forestgreen"		   => "228b22",
		"fuchsia"			   => "ff00ff",
		"gainsboro"			   => "dcdcdc",
		"ghostwhite"		   => "f8f8ff",
		"gold"				   => "ffd700",
		"goldenrod"			   => "daa520",
		"gray"				   => "808080",
		"green"				   => "008000",
		"greenyellow"		   => "adff2f",
		"honeydew"			   => "f0fff0",
		"hotpink"			   => "ff69b4",
		"indianred "		   => "cd5c5c",
		"indigo "			   => "4b0082",
		"ivory"				   => "fffff0",
		"khaki"				   => "f0e68c",
		"lavender"			   => "e6e6fa",
		"lavenderblush"		   => "fff0f5",
		"lawngreen"			   => "7cfc00",
		"lemonchiffon"		   => "fffacd",
		"lightblue"			   => "add8e6",
		"lightcoral"		   => "f08080",
		"lightcyan"			   => "e0ffff",
		"lightgoldenrodyellow" => "fafad2",
		"lightgrey"			   => "d3d3d3",
		"lightgreen"		   => "90ee90",
		"lightpink"			   => "ffb6c1",
		"lightsalmon"		   => "ffa07a",
		"lightseagreen"		   => "20b2aa",
		"lightskyblue"		   => "87cefa",
		"lightslateblue"	   => "8470ff",
		"lightslategray"	   => "778899",
		"lightsteelblue"	   => "b0c4de",
		"lightyellow"		   => "ffffe0",
		"lime"				   => "00ff00",
		"limegreen"			   => "32cd32",
		"linen"				   => "faf0e6",
		"magenta"			   => "ff00ff",
		"maroon"			   => "800000",
		"mediumaquamarine"	   => "66cdaa",
		"mediumblue"		   => "0000cd",
		"mediumorchid"		   => "ba55d3",
		"mediumpurple"		   => "9370d8",
		"mediumseagreen"	   => "3cb371",
		"mediumslateblue"	   => "7b68ee",
		"mediumspringgreen"	   => "00fa9a",
		"mediumturquoise"	   => "48d1cc",
		"mediumvioletred"	   => "c71585",
		"midnightblue"		   => "191970",
		"mintcream"			   => "f5fffa",
		"mistyrose"			   => "ffe4e1",
		"moccasin"			   => "ffe4b5",
		"navajowhite"		   => "ffdead",
		"navy"				   => "000080",
		"oldlace"			   => "fdf5e6",
		"olive"				   => "808000",
		"olivedrab"			   => "6b8e23",
		"orange"			   => "ffa500",
		"orangered"			   => "ff4500",
		"orchid"			   => "da70d6",
		"palegoldenrod"		   => "eee8aa",
		"palegreen"			   => "98fb98",
		"paleturquoise"		   => "afeeee",
		"palevioletred"		   => "d87093",
		"papayawhip"		   => "ffefd5",
		"peachpuff"			   => "ffdab9",
		"peru"				   => "cd853f",
		"pink"				   => "ffc0cb",
		"plum"				   => "dda0dd",
		"powderblue"		   => "b0e0e6",
		"purple"			   => "800080",
		"red"				   => "ff0000",
		"rosybrown"			   => "bc8f8f",
		"royalblue"			   => "4169e1",
		"saddlebrown"		   => "8b4513",
		"salmon"			   => "fa8072",
		"sandybrown"		   => "f4a460",
		"seagreen"			   => "2e8b57",
		"seashell"			   => "fff5ee",
		"sienna"			   => "a0522d",
		"silver"			   => "c0c0c0",
		"skyblue"			   => "87ceeb",
		"slateblue"			   => "6a5acd",
		"slategray"			   => "708090",
		"snow"				   => "fffafa",
		"springgreen"		   => "00ff7f",
		"steelblue"			   => "4682b4",
		"tan"				   => "d2b48c",
		"teal"				   => "008080",
		"thistle"			   => "d8bfd8",
		"tomato"			   => "ff6347",
		"turquoise"			   => "40e0d0",
		"violet"			   => "ee82ee",
		"violetred"			   => "d02090",
		"wheat"				   => "f5deb3",
		"white"				   => "ffffff",
		"whitesmoke"		   => "f5f5f5",
		"yellow"			   => "ffff00",
		"yellowgreen"		   => "9acd32"
	);
	
}


class ParserException extends \Exception {}
class UnknownFormatException extends ParserException {}
