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

/**
 * This class is for rendering a table of data.
 *
 * @package    lnApp
 * @category   lnApp/Helpers
 * @author     Deon George
 * @copyright  (c) 2009-2013 Deon George
 * @license    http://dev.leenooks.net/license.html
 * @uses       Style
 */
abstract class lnApp_Table {
	public static function resolve($d,$key) {
		if (is_array($d) AND isset($d[$key]))
			$x = $d[$key];
		// If the key is a method, we need to eval it
		elseif (preg_match('/\(/',$key) OR preg_match('/-\>/',$key))
			eval("\$x = \$d->$key;");
		elseif (preg_match('/^__VALUE__$/',$key))
			$x = $d;
		else
			$x = $d->display($key);

		return $x;
	}

	public static function display($data,$rows,array $cols,array $option) {
		if (! (array)$data)
			return '';

		$pag = NULL;
		$view = $output = $button = '';

		if (isset($option['type']) AND $option['type'])
			switch ($option['type']) {
				case 'select':
					$view = 'table/select';

					if (! empty($option['button']))
						$button = implode('',$option['button']);
					else
						$button = Form::button('Submit','View/Edit',array('class'=>'form_button','type'=>'submit'));

					Script::add(array(
						'type'=>'stdin',
						'data'=>'
(function($) {
	// Enable Range Selection
	$.fn.enableCheckboxRangeSelection = function() {
		var lastCheckbox = null;
		var followOn = 0;
		var $spec = this;
		$spec.bind("click", function(e) {
			if (lastCheckbox != null && e.shiftKey) {
				x = y = 0;
				if (followOn != 0) {
					if ($spec.index(lastCheckbox) < $spec.index(e.target)) {
						x = 1 - ((followOn == 1) ? 1 : 0);
					} else {
						y = 1 - ((followOn == -1) ? 1 : 0);
					}
				}

				$spec.slice(
					Math.min($spec.index(lastCheckbox) - x, $spec.index(e.target)) + 1,
					Math.max($spec.index(lastCheckbox), $spec.index(e.target)) + y
				).attr("checked",function() { return ! this.checked; })
				.parent().parent().toggleClass("selected");

				followOn = ($spec.index(lastCheckbox) < $spec.index(e.target)) ? 1 : -1;
			} else {
				followOn = 0;
			}
			lastCheckbox = e.target;
		});

		return $spec;
	};

	// Enable Toggle, (De)Select All
	$.fn.check = function(mode) {
		// if mode is undefined, use "on" as default
		var mode = mode || "on";

		switch(mode) {
			case "on":
				$("#select-table tr:not(.head)")
					.filter(":has(:checkbox:not(checked))")
					.toggleClass("selected")
				break;
			case "off":
				$("#select-table tr:not(.head)")
					.filter(":has(:checkbox:checked)")
					.toggleClass("selected")
				break;
			case "toggle":
				$("#select-table tr:not(.head)")
					.toggleClass("selected");
				break;
		}

		return this.each(function(e) {
			switch(mode) {
				case "on":
					this.checked = true;
					break;
				case "off":
					this.checked = false;
					break;
				case "toggle":
					this.checked = !this.checked;
					break;
			}
		});
	};
})(jQuery);

// Bind our actions
$(document).ready(function() {
	$("#select-table :checkbox").enableCheckboxRangeSelection();
	$("#select-menu > #toggle").bind("click",function() {
		$("#select-table :checkbox").check("toggle");
	});
	$("#select-menu > #all_on").bind("click",function() {
		$("#select-table :checkbox").check("on");
	});
	$("#select-menu > #all_off").bind("click",function() {
		$("#select-table :checkbox").check("off");
	});

	// Our mouse over row highlight
	$("#select-table tr:not(.head)").hover(function() {
		$(this).children().toggleClass("highlight");
	},
	function() {
		$(this).children().toggleClass("highlight");
	});

	// Click to select Row
	$("#select-table tr:not(.head)")
		.filter(":has(:checkbox:checked)")
		.addClass("selected")
		.end()
		.click(function(e) {
			$(this).toggleClass("selected");
			if (e.target.type !== "checkbox") {
				$(":checkbox", this).attr("checked", function() {
					return !this.checked;
				});
			}
		});

	// Double click to select a row
	$("#select-table tr:not(.head)")
		.dblclick(function(e) {
			window.location = $("a", this).attr("href");
		});
});
					'));

					$output .= Form::open((isset($option['form']) ? $option['form'] : ''));

					if (! empty($option['hidden']))
						$output .= '<div>'.implode('',$option['hidden']).'</div>';

					break;

				case 'list':
				default:
					Script::add(array(
						'type'=>'stdin',
						'data'=>'
// Bind our actions
$(document).ready(function() {
	// Our mouse over row highlight
	$("#list-table tr:not(.head)").hover(function() {
		$(this).children().toggleClass("highlight");
	},
	function() {
		$(this).children().toggleClass("highlight");
	});
});
					'));
			}

		If (! $view)
			$view = 'table/list';

		if (isset($option['page']) AND $option['page']) {
			$pag = new Pagination(array(
				'total_items'=>count($data),
				'items_per_page'=>$rows,
				));

			$output .= (string)$pag;
		}

		$other = $i = 0;
		$td = $th = array();
		foreach ($cols as $col => $details) {
			$th[$col] = isset($details['label']) ? $details['label'] : '';
			$td[$col]['class'] = isset($details['class']) ? $details['class'] : '';
			$td[$col]['url'] = isset($details['url']) ? $details['url'] : '';
		}

		$output .= View::factory($view.'_head')
			->set('th',array_values($th));

		foreach ($data as $do) {
			if ($pag) {
				if (++$i < $pag->current_first_item())
					continue;
				elseif ($i > $pag->current_last_item())
					break;
			}

			if ($pag OR ($i++ < $rows) OR is_null($rows)) {
				foreach (array_keys($cols) as $col)
					$td[$col]['value'] = Table::resolve($do,$col);

				$output .= View::factory($view.'_body')
					->set('td',$td);

			} elseif (isset($option['show_other']) AND ($col=$option['show_other'])) {
				$other += Table::resolve($do,$col);
			}
		}

		if ($other)
			$output .= View::factory($view.'_xtra')
				->set('td',array_values($cols))
				->set('count',$i-$rows)
				->set('other',$other);

		$output .= View::factory($view.'_foot')
			->set('button',$button);

		if (isset($option['type']) AND $option['type'])
			switch ($option['type']) {
				case 'select':
					$output .= Form::close();
			}

		return $output;
	}

	public static function post($key,$i='id') {
		if (isset($_POST[$i]))
			Session::instance()->set('page_table_view'.$key,$_POST[$i]);
	}

	public static function page($key) {
		// We have preference for parameters passed to the action.
		if (is_null($id = Request::current()->param('id'))) {

			if (isset($_POST['id']) AND is_array($_POST['id']))
				Table::post($key,'id');

			if ($ids = Session::instance()->get('page_table_view'.$key)) {
				$pag = new Pagination(array(
					'total_items'=>count($ids),
					'items_per_page'=>1,
				));

				return array($ids[$pag->current_first_item()-1],(string)$pag);
			}

		}

		// If we get here, then there is no previous data to retrieve.
		return array($id,'');
	}
}
?>
