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

/**
 * This class provides access to Google's Chart Legacy API
 *
 * @package    GoogleChart
 * @category   Helper
 * @author     Deon George
 * @copyright  (c) 2009-2013 Deon George
 * @license    http://dev.leenooks.net/license.html
 */
class GoogleChart_Legacy extends GoogleChart {
	// Chart URL
	private $_url = 'http://chart.apis.google.com/chart';
	// The type of chart we'll plot
	private $_type = 'bvs';
	// Data encoding type to use
	private $_encodetype = 's';
	// Chart Types
	private $cht = array(
		// Line
//		'line'                 => 'lc',
//		'sparkline'            => 'ls',
//		'line_xy'              => 'lxy',
		// Bar
//		'horizontal_bar'       => 'bhs',
		'vertical_bar'         => 'bvs',
//		'horizontal_bar_grp'   => 'bhg',
//		'vertical_bar_grp'     => 'bvg',
		// Pie
//		'pie'                  => 'p',
//		'pie_3d'               => 'p3',
//		'pie_concentric'       => 'pc',
		// Venn
//		'venn'                 => 'v',
		// Scatter
//		'scatter'              => 's',
		// Radar
//		'radar'                => 'r',
//		'radar_fill'           => 'rs',
		// Maps
//		'map'                  => 't',
		// Google-o-meter
//		'google_o_meter'       => 'gom',
		// QR
//		'qr'                   => 'qr',
	);

	/**
	 * Set the type of the chart
	 * @param $type Chart type as per $this->cht
	 */
	public function type($type) {
		if (empty($this->cht[$type]))
			throw new Kohana_Exception('Unknown chart type :type for :class',array(':type'=>$type,':class'=>get_class($this)));

		$this->_type = $this->cht[$type];

		return $this;
	}

	/**
	 * Count how many metrics are being graphed per side
	 * @param $side Side YL (left) OR YR (right)
	 */
	private function axiscount($side) {
		$i = 0;

		foreach ($this->_axis as $l => $axis)
			if ($axis == $side)
				$i++;

		return $i;
	}

	/**
	 * Calculate our maximum for each side of the chart
	 */
	private function maxes() {
		$result = array();

		foreach ($this->_axis as $l => $axis) {
			if (! isset($result[$axis]))
				$result[$axis] = 0;

			$result[$axis] += $this->_max[$l]*1.1; // @todo This scaleup should be configurable
		}

		return $result;
	}

	/** CHART FIELDS **/

	private function chd() {
		$result = array();
		$maxes = $this->maxes();

		// Perform our encoding
		foreach ($this->_axis as $l => $axis)
			array_push($result,$this->encode($this->_data[$l],$maxes[$axis]));

		$prefix = (count($maxes) > 1) ? sprintf('%s:',$this->axiscount('yl')) : ':';

		// If encoding is text, we need to separate the series with a |
		return ($this->_encodetype == 't') ? $prefix.implode('|',$result) : $prefix.implode(',',$result);
	}

	private function chm() {
		$result = array();
		$sc = $this->seriescolors();
		$i = 0;

		foreach ($this->_axis as $l => $axis) {
			if ($axis == 'yr')
				array_push($result,sprintf('%s,%s,%s,%s,%s,%s','D',$sc[$i],$i,0,2,2));// @todo 'D,0,2,2' May need to be configurable

			$i++;
		}
		
		return count($result) ? implode('|',$result) : '';
	}

	private function chxl() {
		$result = array();

		// @todo This should be performed better - it may be a wrong assumption that all keys in the series have data.
		foreach ($this->_data as $series => $data)
			// @todo Why the 0:?
			return '0:|'.implode('|',array_keys($data));
	}

	private function chxr() {
		$result = array();
		$i = 1;

		foreach ($this->maxes() as $key => $value)
			array_push($result,sprintf('%s,0,%s,0',$i++,$value));

		return implode('|',$result);
	}

	public function json() {}

	/**
	 * Return URL that renders the chart
	 */
	public function render() {
		return sprintf('<img src="%s?%s" alt="%s">',$this->_url,http_build_query($this->build()),_('Google Chart'));
	}

	/**
	 * Build the chart
	 */
	private function build() {
		if ($this->_data ) {
			return array(
				'chf'=>'bg,s,FFFFFF00',
				'cht'=>$this->_type,
				'chs'=>sprintf('%sx%s',$this->_width,$this->_height),
				'chtt'=>$this->_title,
				'chbh'=>'a', // @todo This might need to be calculated, valid options (a,r);
				'chg'=>'7.7,12.5,1,5', // @todo This should be calculated
				'chco'=>implode(',',$this->seriescolors()),
				'chdl'=>implode('|',array_keys($this->_axis)),
				'chd'=>$this->_encodetype.$this->chd(),
				'chm'=>$this->chm(),
				'chxt'=>'x,y,r', // @todo configurable?
				'chxl'=>$this->chxl(),
				'chxr'=>$this->chxr(),
			);

		} else
			return array();
	}

	/**
	 * Encode the series data
	 * @param $data String of data to encode
	 * @param $max The maximum to scale to
	 */
	private function encode($data,$max=NULL) {
		$table = array();
		$table['simple'] = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
		$table['extend'] = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-.';

		$size = array();
		$size['simple'] = strlen($table['simple']);
		$size['extend'] = strlen($table['extend']);

		if (is_null($max) OR $max == 0)
			$max = max($data) > 0 ? max($data) : 1;

		$encode = '';

		switch ($this->_encodetype) {
			case 't' :
				return join(',',$data);

			case 's' :
				foreach ($data as $v)
					$encode .= ($v > -1) ? substr($table['simple'],($size['simple']-1)*($v/$max),1) : '_';

				break;

			case 'e' :
				foreach ($data as $v) {
					# Convert to a 0-4095 data range
					$y = 4095*$v/$max;
					$first = substr($table['extend'],floor($y/$size['extend']),1);
					$second = substr($table['extend'],$y%$size['extend'],1);
					$encode .= "$first$second";
				}

				break;
		}

		return $encode;
	}
}
?>
