<?php defined('SYSPATH') or die('No direct access allowed.');

/**
 * This class provides access to Google's Chart API
 *
 * @package    GoogleChart
 * @category   Helper
 * @author     Deon George
 * @copyright  (c) 2009-2013 Deon George
 * @license    http://dev.leenooks.net/license.html
 */
abstract class GoogleChart implements Iterator,Countable {
	// Hold the data for our chart
	protected $_data = array();
	protected $_axis = array();
	private $_plotdata = array();
	protected $_max = array();
	// Chart title
	protected $_title = '';
	protected $_dataurl = '';
	protected $_divname = 'gchart';
	// Default chart size.
	protected $_height = '200';
	protected $_width = '700';

	// Colors to use for series
	private $series_colors = array('AAACCC','E0E0E0','CCC888','EEEBBB','666CCC','888888');

	// Implementation Methods
	public function count() {
		return count($this->_plotdata);
	}
	public function current() {
		return current($this->_plotdata);
	}
	public function key() {
		return key($this->_plotdata);
	}
	public function next() {
		return next($this->_plotdata);
	}
	public function rewind() {
		reset($this->_plotdata);
	}
	public function valid() {
		return key($this->_plotdata) ? TRUE : FALSE;
	}

	public function __call($name,$args) {
		switch ($name) {
			case 'dataurl': $this->_dataurl = array_shift($args);
				break;
			case 'div': $this->_divname = array_shift($args);
				break;
			case 'height': $this->_height = array_shift($args);
				break;
			case 'title': $this->_title = array_shift($args);
				break;
			case 'width': $this->_width = array_shift($args);
				break;
			default:
				throw new Kohana_Exception('Unknown method :name',array(':name'=>$name));
		}

		return $this;
	}

	/**
	 * Render the URL that generates the graph
	 */
	final public function __toString() {
		try {
			return (string)$this->render();
		} catch (Exception $e) {
			echo Debug::vars($e);
		}
	}

	/**
	 * Pick the driver that will render the graph
	 * @param $class The child class to invoke
	 */
	final public static function factory($class) {
		$c = sprintf('%s_%s',get_called_class(),$class);

		if (! class_exists($c))
			throw new Kohana_Exception('Unknown Google Chart Type :class',array(':class'=>$class));
		else
			return new $c();
	}

	// Render the chart data in a json format
	abstract public function json();

	// Our child class should define how to render as a string
	abstract public function render();

	/**
	 * Record one series of data
	 * @param $axis Axis used and legend title, eg: (yr->"Right Y",yl->"Left Y")
	 * @param $data Data for Axis in the format ("x label"=>value);
	 *
	 * Example:
	 * $this->data('yl'=>'Base Down Peak',array('11-12'=>1,'11-11'=>2));
	 */
	public function sdata(array $axis,array $data) {
		// Some sanity checking
		if (count($axis) != 1)
			throw new Kohana_Exception('We can only take 1 series at time.');

		// This should only iterate once
		foreach ($axis as $key => $l) {
			if (! in_array($key,array('yr','yl')))
				throw new Kohaan_Exception('Unknown AXIS :axis',array(':axis'=>$key));

			$this->_axis[$l] = $key;
			$this->_data[$l] = $data[$l];

			// Upate our plot data
			foreach ($data[$l] as $k=>$v)
				$this->_plotdata[$k][$l] = $v;

			ksort($this->_plotdata);

			$this->_max[$l] = max($data[$l]);
		}

		return $this;
	}

	/**
	 * Record on plot event
	 * @param $data Should contain an "X" with a "YL" and/or "YR"
	 */
	public function pdata($x,array $data) {
		if (! is_string($x))
			throw new Kohana_Exception('X should be a string');

		foreach ($data as $key => $values) {
			switch ($key) {
				case 'yr':
				case 'yl':
					foreach ($values as $k=>$v) {
						if (! in_array($k,$this->_axis))
							$this->_axis[$k] = $key;

						$this->_data[$k][$x] = $v;
						$this->_plotdata[$x][$k] = $v;
					}

					break;

				default:
					throw new Kohana_Exception('Unknown key :key',array(':key'=>$key));
			}
		}
	}

	/**
	 * Return the colors that will be used for this series
	 */
	protected function seriescolors() {
		return array_slice($this->series_colors,0,count($this->_axis));
	}

	/**
	 * Render the chart data in a table format
	 */
	public function table($vertical=TRUE,$class=array()) {
		if (! $this->_data)
			return sprintf('<table><tr><td>%s</td></tr></table>',_('No Data'));

		$output = sprintf('<table %s>',
			isset($class['table']) ? $class['table'] : 'class="google-data-table"');

		if ($vertical) {
			$output .= '<tr>';
			$output .= '<td>&nbsp;</td>';
			foreach ($this->_axis as $l => $axis)
				$output .= sprintf('<th style="text-align: right;">%s</th>',$l);

			$output .= '</tr>';

			foreach ($this as $k => $details) {
				$output .= '<tr>';
				$output .= sprintf('<th style="text-align: right;">%s</th>',$k);
				foreach ($this->_axis as $l => $axis)
					$output .= sprintf('<td style="text-align: right;">%s</td>',$details[$l]);
				$output .= '</tr>';
			}

		// Horizontal table
		} else {
			$output .= '<tr>';
			$output .= '<td>&nbsp;</td>';
			foreach ($this as $k => $details)
				$output .= sprintf('<th style="text-align: right;">%s</th>',$k);
			$output .= '</tr>';

			foreach ($this->_axis as $l => $axis) {
				$output .= '<tr>';

				$output .= sprintf('<th style="text-align: right;">%s</th>',$l);

				foreach ($this as $k => $v)
					$output .= sprintf('<td style="text-align: right;">%s</td>',$v[$l]);

				$output .= '</tr>';
			}
		}

		$output .= '</table>';

		return $output;
	}
}
?>