<?php

// EasyGiant is a PHP framework for creating and managing dynamic content
//
// Copyright (C) 2009 - 2011  Antonio Gallo
// See COPYRIGHT.txt and LICENSE.txt.
//
// This file is part of EasyGiant
//
// EasyGiant is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// EasyGiant is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with EasyGiant.  If not, see <http://www.gnu.org/licenses/>.

if (!defined('EG')) die('Direct access not allowed!');

//class to create the HTML of a list of records
class Helper_List extends Helper_Html {

	private $__rowArray = array(); //the current associative array representing the database record

	protected $_itemsList = array(); //2-dimensional associative array containing the list items
	//keys: type,table:field,controller/action,value
	protected $_head = array(); //2-dimensional array containing the head of the table
	protected $_identifierName;

	protected $_recordNumber = null; //number of records from the table

	protected $_allowedItems = array('simpleLink','simpleText','delForm','editForm','associateForm','moveupForm','movedownForm','Form','ledit','link','text'); //type of items allowed

	//it can be: both, top, bottom, none
	protected $_boundaries = 'none';

	//array of filters
	protected $_filters = array();
	
	//set if the submit buttons have to be images or not (it can be yse or not)
	public $submitImageType = 'yes';

	//set the files of the images
	public $submitImages = array();

	//set the titles of the input:submit
	public $submitTitles = array();

	//properties of columns
	public $colProperties = array();

	//table attributes
	public $tableAttributes = array('class'=>'listTable','cellspacing'=>'0');

	//$position: array. First element: page number, second element: number of pages
	public $position = array();

	//instance of Lang_{language}_Generic
	public $strings = null;

	//the url (controller/action) of the current page
	public $url = null;

	public $pageArg = null; //the key of the viewArgs array representing the page number. $this->viewArgs[$this->pageArg] is set to 1 if $this->pageArg !== null
	
	public function __construct() {
		
		//get the generic language class
		$this->strings = Factory_Strings::generic(Params::$language);

		$baseUrl = 'http://'.DOMAIN_NAME.'/Public/Img/Icons/elementary_2_5/';

		//set the files of the images
		$this->submitImages = array(
			'up'	=>	$baseUrl.'up.png',
			'down'	=>	$baseUrl.'down.png',
			'edit'	=>	$baseUrl.'edit.png',
			'del'	=>	$baseUrl.'delete.png',
			'link'	=>	$baseUrl.'link.png',
		);
	
		$this->submitTitles = array(
			'edit'		=>	$this->strings->gtext('edit'),
			'del'		=>	$this->strings->gtext('delete'),
			'up'		=>	$this->strings->gtext('move up'),
			'down'		=>	$this->strings->gtext('move down'),
			'link'		=>	$this->strings->gtext('associate')
		);

	}
	
	public function build($identifierName = 'identifier', $url = null, $pageArg = null)
	{
		$this->_identifierName = $identifierName;
		$this->url = $url;
		$this->pageArg = $pageArg;
	}

	public function setIdentifierName($identifierName)
	{
		$this->_identifierName = $identifierName;
	}

	//add a list Item. $type: the type of the item, $field: the table.field to exctract (use colon to separate the table and the field),$action: controller/action,$value=if type == link->the value of the link
	public function addItem($type, $action = '', $field = '', $name = '', $value = '', $title = '') {
		if (!in_array($type,$this->_allowedItems)) {
			throw new Exception('"'.$type. '" argument not allowed in '.__METHOD__.' method');
		}
		$temp=array();
		$temp['type'] = $type;
		$temp['action'] = $action;
		$temp['field'] = $field;
		$temp['name'] = $name;
		$temp['value'] = $value;
		$temp['title'] = $title;
		$this->_itemsList[] = $temp;

		//set the $this->_head array
		$head = array();
		$head['type'] = $type;

		if ($type === 'simpleText') {
			$head['action'] = $this->extractFieldName($action);
		} else {
			$head['action'] = '&nbsp';
		}
		$this->_head[] = $head;
	}


	//set the head of the table
	//$columnsName: name of the columns. It has to be a comma-separated list of strings
	public function setHead($columnsName = '')
	{
		//get the array from the list
		$columnsArray = explode(',',$columnsName);
		for ($i = 0; $i < count($columnsArray); $i++)
		{
			if ($i < count($this->_itemsList)) $this->_head[$i]['action'] = $columnsArray[$i];
		}
	}

	//set the filters
	//$filters: array whose elements are the viewArgs to be used for the filters forms
	public function setFilters($filters)
	{
		$this->_filters = $filters;
	}

	//check that the ViewArgs array is complete
	public function checkViewArgs()
	{
		foreach ($this->_filters as $field)
		{
			if (!array_key_exists($field,$this->viewArgs) and strcmp($field,null) !== 0) return false;
		}
		return true;
	}
	
	//$method to extract the field name from the $action string (;table:field;). Used for the head
	public function extractFieldName($string) {
		$string = str_replace(';','',$string);
		return $string;
	}

	//replace the strings wrapped by ; with their correspondent value taken by the $recordArray associative array (a row of the select query)
	public function replaceFields($string,$rowArray) {
		$this->__rowArray = $rowArray; //used by the replaceField  method

		$string = preg_replace_callback('/(\;)(.*?)(\;)/', 'Helper_List::replaceField' ,$string);

		return $string;
	}

	//replace a single string wrapped by ; with its correspondent value taken by the $recordArray associative array (a row of the select query)
	public function replaceField($match)
	{
		$string = $match[2];
		
		if (strstr($string,':') or strstr($string,'.')) {
			if (strstr($string,':'))
			{
				$char = ':';
			}
			else
			{
				$char = '.';
			}
			//check if a function has been indicated
			if (strstr($string,'|'))
			{
				//get the function
				$firstArray = explode('|',$string);
				$func = $firstArray[0];
				//replace the fields
				$temp =  explode($char,$firstArray[1]);
				$string = $this->__rowArray[$temp[0]][$temp[1]];

				if (!function_exists($func)) {
					throw new Exception('Error in <b>'.__METHOD__.'</b>: function <b>'.$func.'</b> does not exists..');
				}
				//apply the function
				$string = call_user_func($func,$string);
			}
			else
			{
				$temp = explode($char,$string);
				$string = $this->__rowArray[$temp[0]][$temp[1]];
			}
		}
		return $string;
	}

	//call the method replaceFields upon the $items array using the associative array $rowArray
	public function replaceAll($item,$rowArray) {
		$item['action'] = $this->replaceFields($item['action'],$rowArray);
		$item['field'] = $this->replaceFields($item['field'],$rowArray);
		$item['name'] = $this->replaceFields($item['name'],$rowArray);
		$item['value'] = $this->replaceFields($item['value'],$rowArray);
		$item['title'] = $this->replaceFields($item['title'],$rowArray);
		return $item;
	}

	//wrap the column with the tag td
	public function wrapColumn($string, $className = null) {
		return wrap($string,array('td'=>$className));
	}

	//wrap the row with the tag tr
	public function wrapRow($string,$className = null) {
		return wrap($string,array('tr'=>$className));
	}

	public function wrapList($string) {
		return wrap($string,array('table'=>$this->tableAttributes));
	}

	//method to create the HTML of the head of the table
	public function createHead() {
		$htmlHead = null;
		
		$count = 0;
		foreach ($this->_head as $item) {
			$temp = $item['action'];
			
			$prop = $item['type'];
			if (isset($this->colProperties[$count]))
			{
				$prop = $this->colProperties[$count];
			}
			
			$htmlHead .= $this->wrapColumn($temp,$prop);
			
			$count++;
		}

		return $htmlHead;
	}

	//method to create the HTML of the head of the table
	public function createFilters() {
		$htmlFilters = null;

		if (count($this->_filters) > 0)
		{
			if ($this->checkViewArgs())
			{
				$count = 0;
				foreach ($this->_head as $item) {

					$prop = $item['type'];
					if (isset($this->colProperties[$count]))
					{
						$prop = $this->colProperties[$count];
					}

					$html = '&nbsp';
					if (isset($this->_filters[$count]))
					{
						$html = $this->filterForm($this->_filters[$count]);
					}
					$htmlFilters .= $this->wrapColumn($html,$prop);

					$count++;
				}
			}
		}
		
		return $htmlFilters;
	}

	//create the HTML of a single row (values taken from the associative array $rowArray)
	public function getRowList($rowArray) {
		$htmlList = null;

		$count = 0;
		foreach ($this->_itemsList as $item) {
			$item = $this->replaceAll($item,$rowArray);

			$prop = $item['type'];
			if (isset($this->colProperties[$count]))
			{
				$prop = $this->colProperties[$count];
			}

			if (($this->_boundaries === 'top' and $item['type'] === 'moveupForm') or ($this->_boundaries === 'bottom' and $item['type'] === 'movedownForm') or ($this->_boundaries === 'both' and ($item['type'] === 'moveupForm' or $item['type'] === 'movedownForm')))
			{
				$htmlList .= $this->wrapColumn('&nbsp',$prop);
			}
			else
			{
				$temp = call_user_func_array(array($this,$item['type']),array($item));
				$htmlList .= $this->wrapColumn($temp,$prop);
			}
			$count++;
		}
		return $htmlList;
	}

	//$index: record number
	public function ifInBoundaries($index)
	{
		$this->_boundaries = 'none';
		
		if (!empty($this->position))
		{
			if ($this->_recordNumber === 1 and strcmp($this->position[0],1) === 0)
			{
				$this->_boundaries = 'both';
			}
			else if ($index === 0 and strcmp($this->position[0],1) === 0)
			{
				$this->_boundaries = 'top';
			}
			else if ($index === ($this->_recordNumber-1) and strcmp($this->position[0],$this->position[1]) === 0)
			{
				$this->_boundaries = 'bottom';
			}
		}

	}

	//create the HTML of the entire list. $queryResult: the array coming from the select query
	public function render($queryResult)
	{
		//set the number of records
		$this->_recordNumber = count($queryResult);
		$htmlList = null;
		//create the HTML of the head of the record list
		$htmlList .= $this->wrapRow($this->createHead(),'listHead');
		//create the HTML of the filters
		$htmlList .= $this->wrapRow($this->createFilters(),'listFilters');
		for ($i = 0; $i < count($queryResult); $i++)
		{
			$this->ifInBoundaries($i);
			$temp = $this->getRowList($queryResult[$i]);
			$htmlList .= $this->wrapRow($temp,'listRow');
		}
		return $this->wrapList($htmlList);
	}

	public function generalForm($itemArray, $submitName, $submitValue)
	{
		$string = "<form class='listItemForm' action='".Url::getRoot(null).$itemArray['action'].$this->viewStatus."' method='POST'>\n";
		$name = (strcmp($itemArray['name'],'') !== 0) ? $itemArray['name'] : $submitName;
		$value = (strcmp($itemArray['value'],'') !== 0) ? $itemArray['value'] : $submitValue;

		$oldValue = $value;
		$value = $this->strings->gtext($value);
		
		if (strcmp($itemArray['title'],'') !== 0)
		{
			$title = "title='".$itemArray['title']."'";
		}
		else
		{
			$title = isset($this->submitTitles[$oldValue]) ? "title='".$this->submitTitles[$oldValue]."'" : null;
		}
		
		if (strcmp($this->submitImageType,'yes') === 0 and isset($this->submitImages[$oldValue]))
		{
			$imgSrc = $this->submitImages[$oldValue];
			
			$string .= "<input type='image' $title src='".$imgSrc."' value='$value'>\n";
			$string .= "<input type='hidden' name='".$name."' value='$value'>\n";
		}
		else
		{
			$string .= "<input type='submit' $title name='".$name."' value='$value'>\n";
		}
		
		$string .= "<input type='hidden' name='".$this->_identifierName."' value='".$itemArray['field']."'>\n";
		$string .= "</form>\n";
		return $string;
	}

	public function Form($itemArray)
	{
		return $this->generalForm($itemArray, 'name_missing', 'value_missing');
	}
	
	public function moveupForm($itemArray)
	{
		return $this->generalForm($itemArray, 'moveupAction', 'up');
	}

	public function movedownForm($itemArray)
	{
		return $this->generalForm($itemArray, 'movedownAction', 'down');
	}

	public function editForm($itemArray)
	{
		return $this->generalForm($itemArray, 'generalAction', 'edit');
	}

	public function delForm($itemArray)
	{
		return $this->generalForm($itemArray, 'delAction', 'del');
	}

	public function associateForm($itemArray)
	{
		return $this->generalForm($itemArray, 'generalAction', 'link');
	}

	public function simpleText($itemArray) {
		$text = strcmp($itemArray['action'],'') !== 0 ? $itemArray['action'] : '&nbsp';
		$string = "<span class='textItem'>".$text."</span>\n";
		return $string;
	}

	public function text($itemArray)
	{
		return $this->simpleText($itemArray);
	}
	
	public function simpleLink($itemArray) {
		$string = "<a title='".$itemArray['field']."' class='linkItem' href='".Url::getRoot(null).$itemArray['action'].$this->viewStatus."'>".$itemArray['name']."</a>\n";
		return $string;
	}

	public function link($itemArray)
	{
		return $this->simpleLink($itemArray);
	}

	public function ledit($itemArray)
	{
		$text = isset($this->submitImages['edit']) ? "<img src='".$this->submitImages['edit']."'>" : $itemArray['name'];
		$title = isset($this->submitTitles['edit']) ? $this->submitTitles['edit'] : $itemArray['field'];
		$string = "<a title='".$title."' class='linkItem' href='".Url::getRoot(null).$itemArray['action'].$this->viewStatus."'>$text</a>\n";
		return $string;
	}

	//create the HTML of the filter
	public function filterForm($viewArgsName)
	{
		$cleanName = str_replace('n!',null,$viewArgsName);
		$cleanName = str_replace('-',null,$cleanName);

		if (isset($this->viewArgs[$this->pageArg]))
		{
			$this->viewArgs[$this->pageArg] = 1;
		}
		
		$temp = $value = $this->viewArgs[$viewArgsName];
		//set the viewArg to the null query value
		if (Params::$nullQueryValue)
		{
			$this->viewArgs[$viewArgsName] = Params::$nullQueryValue;
			$viewStatus = Url::createUrl(array_values($this->viewArgs));
			if (strcmp($value,Params::$nullQueryValue) === 0) $value = '';
		}
		$this->viewArgs[$viewArgsName] = $temp;
		
		$action = Url::getRoot($this->url).$viewStatus;
		$imgSrc = Url::getRoot('Public/Img/Icons/elementary_2_5/find.png');
		$title = $this->strings->gtext('filter');
		$clearLinkTitle = $this->strings->gtext('clear the filter');
		
		$html = "<form class='list_filter_form list_filter_form_$cleanName' action='".$action."' method='GET'>\n";
		$html .= "<input class='list_filter_input list_filter_input_$cleanName' type='text' name='$viewArgsName' value='".$value."'>";
		$html .= "<a class='list_filter_clear_link list_filter_clear_link_$cleanName' title='$clearLinkTitle' href='$action'><img src='".Url::getRoot()."/Public/Img/Icons/elementary_2_5/clear_filter.png' /></a>";
		$html .= "<input class='list_filter_submit list_filter_submit_$cleanName' type='image' title='$title' src='".$imgSrc."' value='trova'>\n";
		$html .= "</form>\n";

		return $html;
	}
	
}