<?php
/*
 * This work is hereby released into the Public Domain.
 * To view a copy of the public domain dedication,
 * visit http://creativecommons.org/licenses/publicdomain/ or send a letter to
 * Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.
 *
 */



/**
 * Some legends
 *
 * @package Artichow
 */
class awLegend implements awPositionable {

	/**
	 * Legends added
	 *
	 * @var array
	 */
	protected $legends = array();

	/**
	 * The current component
	 *
	 * @var Component
	 */
	protected $component;

	/**
	 * Background color or gradient
	 *
	 * @var Color, Gradient
	 */
	protected $background;

	/**
	 * Text color
	 *
	 * @var Color
	 */
	protected $textColor;

	/**
	 * Text font
	 *
	 * @var Font
	 */
	protected $textFont;

	/**
	 * Text margin
	 *
	 * @var Side
	 */
	protected $textMargin;

	/**
	 * Number of columns
	 *
	 * @var int
	 */
	protected $columns = NULL;

	/**
	 * Number of rows
	 *
	 * @var int
	 */
	protected $rows = NULL;

	/**
	 * Legend position
	 *
	 * @var Point
	 */
	protected $position;

	/**
	 * Hide legend ?
	 *
	 * @var bool
	 */
	protected $hide = FALSE;

	/**
	 * Space between each legend
	 *
	 * @var int
	 */
	protected $space = 4;

	/**
	 * Horizontal alignment
	 *
	 * @var int
	 */
	protected $hAlign;

	/**
	 * Vertical alignment
	 *
	 * @var int
	 */
	protected $vAlign;

	/**
	 * Margin
	 *
	 * @var array Array for left, right, top and bottom margins
	 */
	private $margin;

	/**
	 * Legend shadow
	 *
	 * @var Shadow
	 */
	public $shadow;

	/**
	 * Legend border
	 *
	 * @var Border
	 */
	public $border;

	/**
	 * Line legend
	 *
	 * @var int
	 */
	const LINE = 1;

	/**
	 * Color/Gradient background legend
	 *
	 * @var int
	 */
	const BACKGROUND = 2;

	/**
	 * Use marks and line as legend
	 *
	 * @var int
	 */
	const MARK = 3;

	/**
	 * Use marks as legend
	 *
	 * @var int
	 */
	const MARKONLY = 4;

	/**
	 * Right side model
	 *
	 * @var int
	 */
	const MODEL_RIGHT = 1;

	/**
	 * Bottom side model
	 *
	 * @var int
	 */
	const MODEL_BOTTOM = 2;

	/**
	 * Build the legend
	 *
	 * @param int $model Legend model
	 */
	public function __construct($model = awLegend::MODEL_RIGHT) {

		$this->shadow = new awShadow(awShadow::LEFT_BOTTOM);
		$this->border = new awBorder;

		$this->textMargin = new awSide(4);
		$this->setModel($model);

	}

	/**
	 * Set a predefined model for the legend
	 *
	 * @param int $model
	 */
	public function setModel($model) {

		$this->setBackgroundColor(new awColor(255, 255, 255, 15));
		$this->setPadding(8, 8, 8, 8);
		$this->setTextFont(new awFont2);
		$this->shadow->setSize(3);

		switch($model) {

			case awLegend::MODEL_RIGHT :

				$this->setColumns(1);
				$this->setAlign(awLegend::RIGHT, awLegend::MIDDLE);
				$this->setPosition(0.96, 0.50);

				break;

			case awLegend::MODEL_BOTTOM :

				$this->setRows(1);
				$this->setAlign(awLegend::CENTER, awLegend::TOP);
				$this->setPosition(0.50, 0.92);

				break;

			default :

				$this->setPosition(0.5, 0.5);

				break;

		}

	}

	/**
	 * Hide legend ?
	 *
	 * @param bool $hide TRUE to hide legend, FALSE otherwise
	 */
	public function hide($hide = TRUE) {
		$this->hide = (bool)$hide;
	}

	/**
	 * Show legend ?
	 *
	 * @param bool $show
	 */
	public function show($show = TRUE) {
		$this->hide = (bool)!$show;
	}


	/**
	 * Add a Legendable object to the legend
	 *
	 * @param awLegendable $legendable
	 * @param string $title Legend title
	 * @param int $type Legend type (default to awLegend::LINE)
	 */
	public function add(awLegendable $legendable, $title, $type = awLegend::LINE) {

		$legend = array($legendable, $title, $type);

		$this->legends[] = $legend;

	}

	/**
	 * Change legend padding
	 *
	 * @param int $left
	 * @param int $right
	 * @param int $top
	 * @param int $bottom
	 */
	public function setPadding($left, $right, $top, $bottom) {
		$this->padding = array((int)$left, (int)$right, (int)$top, (int)$bottom);
	}

	/**
	 * Change space between each legend
	 *
	 * @param int $space
	 */
	public function setSpace($space) {
		$this->space = (int)$space;
	}

	/**
	 * Change alignment
	 *
	 * @param int $h Horizontal alignment
	 * @param int $v Vertical alignment
	 */
	public function setAlign($h = NULL, $v = NULL) {
		if($h !== NULL) {
			$this->hAlign = (int)$h;
		}
		if($v !== NULL) {
			$this->vAlign = (int)$v;
		}
	}

	/**
	 * Change number of columns
	 *
	 * @param int $columns
	 */
	public function setColumns($columns) {
		$this->rows = NULL;
		$this->columns = (int)$columns;
	}

	/**
	 * Change number of rows
	 *
	 * @param int $rows
	 */
	public function setRows($rows) {
		$this->columns = NULL;
		$this->rows = (int)$rows;
	}

	/**
	 * Change legend position
	 * X and Y positions must be between 0 and 1.
	 *
	 * @param float $x
	 * @param float $y
	 */
	public function setPosition($x = NULL, $y = NULL) {
		$x = (is_null($x) and !is_null($this->position)) ? $this->position->x : $x;
		$y = (is_null($y) and !is_null($this->position)) ? $this->position->y : $y;

		$this->position = new awPoint($x, $y);
	}

	/**
	 * Get legend position
	 *
	 * @return Point
	 */
	public function getPosition() {
		return $this->position;
	}

	/**
	 * Change text font
	 *
	 * @param awFont $font
	 */
	public function setTextFont(awFont $font) {
		$this->textFont = $font;
	}

	/**
	 * Change text margin
	 *
	 * @param int $left
	 * @param int $right
	 */
	public function setTextMargin($left, $right) {
		$this->textMargin->set($left, $right);
	}

	/**
	 * Change text color
	 *
	 * @param awColor $color
	 */
	public function setTextColor(awColor $color) {
		$this->textColor = $color;
	}

	/**
	 * Change background
	 *
	 * @param mixed $background
	 */
	public function setBackground($background) {
		$this->background = $background;
	}

	/**
	 * Change background color
	 *
	 * @param awColor $color
	 */
	public function setBackgroundColor(awColor $color) {
		$this->background = $color;
	}

	/**
	 * Change background gradient
	 *
	 * @param awGradient $gradient
	 */
	public function setBackgroundGradient(awGradient $gradient) {
		$this->background = $gradient;
	}

	/**
	 * Count the number of Legendable objects in the legend
	 *
	 * @return int
	 */
	public function count() {
		return count($this->legends);
	}

	public function draw(awDrawer $drawer) {

		if($this->hide) {
			return;
		}

		$count = $this->count();

		// No legend to print
		if($count === 0) {
			return;
		}

		// Get text widths and heights of each element of the legend
		$widths = array();
		$heights = array();
		$texts = array();
		for($i = 0; $i < $count; $i++) {
			list(, $title, ) = $this->legends[$i];
			$text = new awText(
				$title,
				$this->textFont,
				$this->textColor,
				0
			);
			$font = $text->getFont();
			$widths[$i] = $font->getTextWidth($text) + $this->textMargin->left + $this->textMargin->right;
			$heights[$i] = $font->getTextHeight($text);
			$texts[$i] = $text;
		}

		// Maximum height of the font used
		$heightMax = array_max($heights);

		// Get number of columns
		if($this->columns !== NULL) {
			$columns = $this->columns;
		} else if($this->rows !== NULL) {
			$columns = ceil($count / $this->rows);
		} else {
			$columns = $count;
		}

		// Number of  rows
		$rows = (int)ceil($count / $columns);

		// Get maximum with of each column
		$widthMax = array();
		for($i = 0; $i < $count; $i++) {
			// Get column width
			$column = $i % $columns;
			if(array_key_exists($column, $widthMax) === FALSE) {
				$widthMax[$column] = $widths[$i];
			} else {
				$widthMax[$column] = max($widthMax[$column], $widths[$i]);
			}
		}

		$width = $this->padding[0] + $this->padding[1] - $this->space;
		for($i = 0; $i < $columns; $i++) {
			$width += $this->space + 5 + 10 + $widthMax[$i];
		}

		$height = ($heightMax + $this->space) * $rows - $this->space + $this->padding[2] + $this->padding[3];

		// Look for legends position
		list($x, $y) = $drawer->getSize();

		$p = new awPoint(
			$this->position->x * $x,
			$this->position->y * $y
		);

		switch($this->hAlign) {

			case awLegend::CENTER :
				$p->x -= $width / 2;
				break;

			case awLegend::RIGHT :
				$p->x -= $width;
				break;

		}

		switch($this->vAlign) {

			case awLegend::MIDDLE :
				$p->y -= $height / 2;
				break;

			case awLegend::BOTTOM :
				$p->y -= $height;
				break;

		}

		// Draw legend shadow
		$this->shadow->draw(
			$drawer,
			$p,
			$p->move($width, $height),
			awShadow::OUT
		);

		// Draw legends base
		$this->drawBase($drawer, $p, $width, $height);

		// Draw each legend
		for($i = 0; $i < $count; $i++) {

			list($component, $title, $type) = $this->legends[$i];

			$column = $i % $columns;
			$row = (int)floor($i / $columns);

			// Get width of all previous columns
			$previousColumns = 0;
			for($j = 0; $j < $column; $j++) {
				$previousColumns += $this->space + 10 + 5 + $widthMax[$j];
			}

			// Draw legend text
			$drawer->string(
				$texts[$i],
				$p->move(
					$this->padding[0] + $previousColumns + 10 + 5 + $this->textMargin->left,
					$this->padding[2] + $row * ($heightMax + $this->space) + $heightMax / 2 - $heights[$i] / 2
				)
			);

			// Draw legend icon
			switch($type) {

				case awLegend::LINE :
				case awLegend::MARK :
				case awLegend::MARKONLY :

					// Get vertical position
					$x = $this->padding[0] + $previousColumns;
					$y = $this->padding[2] + $row * ($heightMax + $this->space) + $heightMax / 2 - $component->getLegendLineThickness();

					// Draw two lines
					if($component->getLegendLineColor() !== NULL) {

						$color = $component->getLegendLineColor();

						if($color instanceof awColor and $type !== awLegend::MARKONLY) {

							$drawer->line(
								$color,
								new awLine(
									$p->move(
										$x, // YaPB ??
										$y + $component->getLegendLineThickness() / 2
									),
									$p->move(
										$x + 10,
										$y + $component->getLegendLineThickness() / 2
									),
									$component->getLegendLineStyle(),
									$component->getLegendLineThickness()
								)
							);

							$color->free();
							unset($color);

						}

					}

					if($type === awLegend::MARK or $type === awLegend::MARKONLY)  {

						$mark = $component->getLegendMark();

						if($mark !== NULL) {
							$mark->draw(
								$drawer,
								$p->move(
									$x + 5.5,
									$y + $component->getLegendLineThickness() / 2
								)
							);
						}

						unset($mark);

					}

					break;

				case awLegend::BACKGROUND :

					// Get vertical position
					$x = $this->padding[0] + $previousColumns;
					$y = $this->padding[2] + $row * ($heightMax + $this->space) + $heightMax / 2 - 5;

					$from = $p->move(
						$x,
						$y
					);

					$to = $p->move(
						$x + 10,
						$y + 10
					);

					$background = $component->getLegendBackground();

					if($background !== NULL) {

						$drawer->filledRectangle(
							$component->getLegendBackground(),
							new awLine($from, $to)
						);

						// Draw rectangle border
						$this->border->rectangle(
							$drawer,
							$from->move(0, 0),
							$to->move(0, 0)
						);

					}

					unset($background, $from, $to);

					break;

			}

		}

			// Draw legend text
		/*	$drawer->string(
				$texts[$i],
				$p->move(
					$this->padding[0] + $previousColumns + 10 + 5 + $this->textMargin->left,
					$this->padding[2] + $row * ($heightMax + $this->space) + $heightMax / 2 - $heights[$i] / 2
				)
			);*/



		$text1 = new awText(
			'Weekly',
			new Tuffy(8),
			new Color(0, 0, 0, 0),
			0);

		$text2 = new awText(
			'Monthly',
			new Tuffy(8),
			new Color(0, 0, 0, 0),
			0);
			
		$text3 = new awText(
			'Yearly',
			new Tuffy(8),
			new Color(0, 0, 0, 0),
			0);

		$point1 = new awPoint(
			412,
			7
		);	 
		
		$point2 = new awPoint(
			412,
			30
		);	
		
		$point3 = new awPoint(
			412,
			54
		);	
		   
        $drawer->string($text1, $point1);
        $drawer->string($text2, $point2);
        $drawer->string($text3, $point3);

	}

	private function drawBase(awDrawer $drawer, awPoint $p, $width, $height) {

		$this->border->rectangle(
			$drawer,
			$p,
			$p->move($width, $height)
		);

		$size = $this->border->visible() ? 1 : 0;

		$drawer->filledRectangle(
			$this->background,
			new awLine(
				$p->move($size, $size),
				$p->move($width - $size, $height - $size)
			)
		);

	}

}

registerClass('Legend');

/**
 * You can add a legend to components which implements this interface
 *
 * @package Artichow
 */
interface awLegendable {

	/**
	 * Get the line type
	 *
	 * @return int
	 */
	public function getLegendLineStyle();

	/**
	 * Get the line thickness
	 *
	 * @return int
	 */
	public function getLegendLineThickness();

	/**
	 * Get the color of line
	 *
	 * @return Color
	 */
	public function getLegendLineColor();

	/**
	 * Get the background color or gradient of an element of the component
	 *
	 * @return Color, Gradient
	 */
	public function getLegendBackground();

	/**
	 * Get a Mark object
	 *
	 * @return Mark
	 */
	public function getLegendMark();

}

registerInterface('Legendable');
?>