<?php namespace Color;
class Color {

	/** @var float The amount of red color, from from 0.0 to 1.0. **/
	private $red;

	/** @var float The amount of green color, from from 0.0 to 1.0. **/
	private $green;

	/** @var float The amount of blue color, from from 0.0 to 1.0. **/
	private $blue;

	/** @var float The opacity, from 0.0 to 1.0. **/
	private $opacity;

	/**
	 * Initialize color.
	 *
	 * @param	float	$opacity	The opacity, from 0.0 to 1.0.
	 * @param	float	$red		The amount of blue color, from from 0.0 to 1.0.
	 * @param	float	$green		The amount of blue color, from from 0.0 to 1.0.
	 * @param	float	$blue		The amount of blue color, from from 0.0 to 1.0.
	 *
	 * @throws	Exception	If any of the supplied parameters are not a float between 0 and 1.
	 */
	public function __construct($opacity, $red, $green, $blue) {
		$this->opacity	= self::isValidFloat($opacity);
		$this->red		= self::isValidFloat($red);
		$this->green	= self::isValidFloat($green);
		$this->blue		= self::isValidFloat($blue);
	}

	/**
	 * Initialize color from the supplied hex.
	 *
	 * @param	string	$hex	The hex to parse. Supported formats are RGB, ARGB, RRGGBB and AARRGGBB, with or without leading #.
	 *
	 * @return	Color	The parsed color.
	 *
	 * @throws	Exception	If the supplied hex could not be parsed.
	 */
	public static function makeFromHex($hex) {

		# Make regexp
		$d = '[0-9A-Z]';
		$regexp = strlen($hex) > 4
			? "(?P<opacity>({$d}{$d})?)(?P<red>{$d}{$d})(?P<green>{$d}{$d})(?P<blue>{$d}{$d})"
			: "(?P<opacity>({$d})?)(?P<red>{$d})(?P<green>{$d})(?P<blue>{$d})";

		# Match
		if(!preg_match("~\b#?{$regexp}\b~ i", trim($hex), $color)) {
			throw new Exception\UnknownColorFormatException($hex);
		}

		# Combine
		return new self(
			$color['opacity'] ? hexdec($color['opacity']) / 255 : 1,
			hexdec($color['red']) / 255,
			hexdec($color['green']) / 255,
			hexdec($color['blue']) / 255
		);
	}

	/**
	 * Allocate color for the supplued canvas.
	 *
	 * @param	resource	$canvas	The canvas for which the color is being allocated.
	 *
	 * @return	The color for the canvas.
	 **/
	public function allocateColor($canvas) {
		return imagecolorallocate($canvas, $this->red * 255, $this->green * 255, $this->blue * 255);
	}

	/**
	 * Validate that the value is a valid float.
	 *
	 * @param	float	$var	The value to test.
	 * @param	staring	$name	The optional name for debugging purposes.
	 *
	 * @return	float	The float value of the supplied variable.
	 *
	 * @throws	Exception	If supplied variable is not a float between 0 and 1.
	 */
	private static function isValidFloat($var, $name = null) {
		$error = null;

		# Get the error
		if($var > 1) {
			$error = 'greater then 1.0';
		} else if($var < 0) {
			$error = 'less then 0.0';
		}

		# Create text
		if($error) {
			throw new Exception\BadFloatValueException($var, $name);
		}

		return (float) $var;
	}

}
