<?php
	
class AKB_AdminTable {

	/**
	* @var array The headings for the table.
	*/	
	var $headingArray = array();

	/**
	* @var array Main processed data array for the table data.
	*/
	var $dataArray = array();
	
	/**
	* @var array Used internally to store callback information
	*/
	var $callBackArray = array();
	
	/**
	* @var array Used internally to store template override information
	*/	
	var $templateOverride = array();

	/**
	* @var resource the resource from a database query.
	*/	
	var $rsData;
	var $rsArray;
	
	
	var $includeSelectors = true;
	var $selectorIconTemplate = "";
	
	var $prependHeader = array();
	var $prependDataTemplate = array();
	
	var $prependDataID;
	
	var $_checkbox_str;
	var $_icon_str;
	
	var $sortArray = array();
	
	var $sizeArray = array();
	
	var $selectorCellWidth = "28px";
	
	var $tableIdent = "";
	
	/**
	* Constructor - Init. Mainly used for the prepend stuff.
	*
	* @return void
	*/
	function AKB_AdminTable() {
	
		$GLOBALS['AKB_CLASS_TEMPLATE']->SetTemplate('admintable.selector.check.header');
		$checkbox = $GLOBALS['AKB_CLASS_TEMPLATE']->LoadTemplateFile(true);
		
		$this->prependHeader['CHECKBOX'] = $checkbox;
		$this->prependHeader['ICON'] = "&nbsp;";
		
		$this->prependDataTemplate['CHECKBOX'] = "admintable.cell.selector.check";
		$this->prependDataTemplate['ICON'] = "admintable.cell.selector.icon";
		
		$GLOBALS['AKB_CLASS_TEMPLATE']->SetTemplate($this->prependDataTemplate['CHECKBOX']);
		$this->_checkbox_str = $GLOBALS['AKB_CLASS_TEMPLATE']->LoadTemplateFile(true);

		$GLOBALS['AKB_CLASS_TEMPLATE']->SetTemplate($this->prependDataTemplate['ICON']);
		$this->_icon_str = $GLOBALS['AKB_CLASS_TEMPLATE']->LoadTemplateFile(true);
	}
	
	/**
	* Main output function. Call this once you have all params set up.
	*
	* @return string Returns HTML string culminated from given data.
	*/	
	function ReturnTable() {
	
		if (($this->rsData) && (!$this->dataArray)) {
			$this->processRecordSet();
		}
		
		if ((!$this->headingArray) || (!is_array($this->headingArray))) {
			return;
		}
		
		$table_string 			= "";
		$header_string 			= "";
		$heading_row_string 	= "";
		$heading_cell_string 	= "";
		$body_row_string 		= "";
		$body_cell_string 		= "";
		
		//Load the data cell.
		$GLOBALS['AKB_CLASS_TEMPLATE']->SetTemplate('admintable.cell');
		$cell_base = $GLOBALS['AKB_CLASS_TEMPLATE']->LoadTemplateFile(true);
		
		//Load the header cell.
		$GLOBALS['AKB_CLASS_TEMPLATE']->SetTemplate('admintable.cell.header');
		$cell_base_header = $GLOBALS['AKB_CLASS_TEMPLATE']->LoadTemplateFile(true);		
		
		$GLOBALS['TableIdent'] = $this->tableIdent;
		
		$this->processHeadingSelectors();
		
		//Culminate the heading cells
		$i = -2;
		foreach ($this->headingArray as $field=>$header) {
			
			$GLOBALS['CellData'] = $header;
			
			if (isset($this->sortArray[$field])) {
				//Handle field selectors
				$GLOBALS['ThisField'] = $field;
				$GLOBALS['Sort'] = $this->sortArray[$field];
			} else {
				$GLOBALS['ThisField'] = "";
				$GLOBALS['Sort'] = "";
			}
			
			if ((isset($this->sizeArray[$i])) && ((int)$this->sizeArray[$i] > 0)) {
				$GLOBALS['Extra'] = "valign=\"middle\" width=\"".$this->sizeArray[$i]."\"";
			} else if ($i < 0) {
				$GLOBALS['Extra'] = "align=\"center\" valign=\"middle\"";
			} else {
				$GLOBALS['Extra'] = "";
			}
			
			$heading_cell_string .= $GLOBALS['AKB_CLASS_TEMPLATE']->ParseTemplate(true,$cell_base_header);			
			
			$i++;
		}
		
		//Put the cells into the rows
		$GLOBALS['Cells'] = $heading_cell_string;
		$GLOBALS['AKB_CLASS_TEMPLATE']->SetTemplate('admintable.row.header');
		$heading_row_string = $GLOBALS['AKB_CLASS_TEMPLATE']->ParseTemplate(true);		
		
		//Culminate the data cells
		foreach ($this->dataArray as $thisRowArray) {
			$body_cell_string = "";
			
			$i = -2; //TODO:: Magic Number!!
			foreach ($thisRowArray as $cellData) {
				if (($this->includeSelectors) && ($i < 0)) { //TODO:: Magic Number
					$GLOBALS['Extra'] = "align=\"center\"  valign=\"middle\" width=\"".$this->selectorCellWidth."\"";
				} else if (isset($this->sizeArray[$i])) {
					$GLOBALS['Extra'] = "valign=\"middle\" width=\"".$this->sizeArray[$i]."\" ";
				} else {
					$GLOBALS['Extra'] = "";
				}
				
				if (is_array($cellData)) {
					//Template Override
					$cellDataArray = $cellData[1];
					$templateOverride = $cellData[0];
					
					foreach ($cellDataArray as $index=>$val) {
						$GLOBALS['CellData'.$index] = $val;	
					}
					$GLOBALS['CellData'] = $cellData;
					$GLOBALS['AKB_CLASS_TEMPLATE']->SetTemplate($templateOverride);
					$body_cell_string .= $GLOBALS['AKB_CLASS_TEMPLATE']->ParseTemplate(true);
				} else {
					//Standard Cell
					$GLOBALS['CellData'] = $cellData;
					$body_cell_string .= $GLOBALS['AKB_CLASS_TEMPLATE']->ParseTemplate(true,$cell_base);				
				}
			
				$i++;
			}
			
			//Put the data cells into the row and keep going
			$GLOBALS['Cells'] = $body_cell_string;
			$GLOBALS['AKB_CLASS_TEMPLATE']->SetTemplate('admintable.row.data');
			$body_row_string .= $GLOBALS['AKB_CLASS_TEMPLATE']->ParseTemplate(true);					
		}
		
		//Put the heading cells and the data cells togethor
		//Put in the table wrapper.
		//Put the cells into the rows
		$GLOBALS['AdminTableRows'] = $heading_row_string.$body_row_string;
		$GLOBALS['AKB_CLASS_TEMPLATE']->SetTemplate('admintable.table');
		$table_string = $GLOBALS['AKB_CLASS_TEMPLATE']->ParseTemplate(true);
		
		return $table_string;
	}
	
	/**
	* Process the recordset into the format that ReturnTable can use.
	*
	* @return void
	*/	
	function processRecordSet() {
		
		if (gettype($this->rsData) == "resource") {
			//If we've been passed a resource then we need to get it out into a more
			//palatable array
			$this->rsArray = array();
			while ($tempRow = $GLOBALS['AKB_DB']->Fetch($this->rsData)) {
				$this->rsArray[] = $tempRow;
			}
		}
		
		if ((gettype($this->rsArray) != "array") || (!$this->rsArray)) {
			//We have no data, return false.
			return false;
		}

		$this->dataArray = array();
		
		$i = 0;
		
		foreach ($this->rsArray as $tempRow) {
			$index = 0;
			$firstTime = true;

			if ($this->includeSelectors) {
				$GLOBALS['currentId'] = $tempRow[$this->prependDataID];
				$this->processDataSelectors();

				$this->dataArray[$i][] = $this->prependData['PRE0'];
				$this->dataArray[$i][] = $this->prependData['PRE1'];
			}

			foreach ($this->headingArray as $dbField=>$header) {

				if (isset($tempRow[$dbField])) {

					//Process User generated callbacks
					if ($firstTime) {
						//The first time through lets add all callbacks for fields that dont actually exist in the recordset
						//ie user created fields

						foreach ($this->callBackArray as $tempField=>$val) {
							if (!isset($tempRow[$tempField])) {
								//OK we need to process this as a new part of the row.
								$tempRow[$tempField] = "";
								if (isset($this->callBackArray[$tempField])) {
									$this->processCallBack($tempField,$this->callBackArray[$tempField],$tempRow,$tempRow[$tempField]);
								}
							}
						}

						$firstTime = false;
					}

					//Process Callbacks
					if (isset($this->callBackArray[$dbField])) {
						$this->processCallBack($dbField,$this->callBackArray[$dbField],$tempRow,$tempRow[$dbField]);
					}

					//Process Template Overrides
					if (isset($this->templateOverride[$dbField])) {
						$this->processTemplateOverride($tempRow[$dbField],$this->templateOverride[$dbField],$dbField,$tempRow);
					}

					//Add the Data
					$this->dataArray[$i][] = $tempRow[$dbField];
				}
			}

			$i++;	
		}
	}
	
	/**
	* Adds a callback function to a specified field in the recordset. Can also create a new field using this so that it can be used by other callbacks 
	* or template overrides.
	*
	* @param $field string The field to add the callback to
	* @param $function string The function to be called
	* @param $params array The params array to pass to the function. Any ones that look like __this__ will be replaced the the fieldname
	* using _processParamReplacement();
	*
	* @return void
	*/	
	function addCallBack($field,$function,$params) {
		$this->callBackArray[$field] = array($function,$params);
	}
	
	/**
	* Process the callback variables.
	*
	* @param $field string The field to process the callback on
	* @param $cbArray string The call back array
	* @param &$currentRow array The current row in the iteration
	* @param &$fieldData string The final output.
	*
	* @return void
	*/	
	function processCallBack($field,$cbArray,&$currentRow,&$fieldData) {
		$functionName 	= $cbArray[0];
		$_paramsArray 	= $cbArray[1];
		
		$paramsArray = $this->_processParamReplacement($_paramsArray,$field,$currentRow);
		
		//Now we check if the functions exists and call it if so.
		if (((is_string($functionName)) && (function_exists($functionName))) || (is_array($functionName))) {
			$fieldData = call_user_func_array($functionName,$paramsArray);			
		}
	}
	
	/**
	* addTemplateOverride: Add Template Override
	*
	* @param $field string The field to process the template override on
	* @param $template string The replacement template name
	* @param $dataArray array The variables to replace. Note the order given is important to match up with the template.
	*
	* @return void
	*/	
	function addTemplateOverride($field,$template,$dataArray=array()) {
		$this->templateOverride[$field] = array($template,$dataArray);
	}
	
	/**
	* processTemplateOverride: Process Template Overrides
	*
	* @param &$data string The final output
	* @param $templateOArray string The template replace array. This gets processed just like the callback.
	* @param $field string The field to use
	* @param $currentRow array The current row in the iteration.
	*
	* @return void
	*/
	function processTemplateOverride(&$data,$templateOArray,$field,$currentRow) {
		$templateOArray[1] = $this->_processParamReplacement($templateOArray[1],$field,$currentRow);
		$data = $templateOArray;
	}
	
	/**
	* _processParamReplacement: Process the replacement variables for the callbacks and the template overrides
	*
	* @param $parray array The param array in which to base the processing on.
	* @param $field string The field to use
	* @param $currentRow array The current row in the iteration.
	*
	* @return paramArray array The processed parameter array
	*/	
	function _processParamReplacement($parray,$field,$currentRow) {
	
		$paramsArray = array();
	
		//We have to go through the params to see if there are any replacement through the current recordset.
		if (is_array($parray)) {
			foreach ($parray as $internalReference) {
				if ((substr($internalReference,0,2) == "__") && (substr($internalReference,-2) == "__")) {
					//Replace param found, make sure we have an instance of it in the data.
					$fieldName = substr($internalReference,2,-2);
					$paramsArray[] = $currentRow[$fieldName];
				} else {
					$paramsArray[] = $internalReference;
				}
			}	
		} else {
			//If its not an array then we simply place the string.
			$paramsArray[] = $parray;
		}
		
		return $paramsArray;
	}
	
	function processHeadingSelectors() {
		if ($this->includeSelectors) {
			$this->headingArray = $this->prependHeader + $this->headingArray;
		}
	}
	
	function processDataSelectors() {
		$checkbox = $this->_checkbox_str;
		$icon = $this->_icon_str;
		
		$this->prependData['PRE0'] = $GLOBALS['AKB_CLASS_TEMPLATE']->ParseTemplate(true,$checkbox);
		$this->prependData['PRE1'] = $GLOBALS['AKB_CLASS_TEMPLATE']->ParseTemplate(true,$icon);
	}
}

?>