<?php

/**
 *
 * @author Peter Csubak (chuby)
 * @copyright Peter Csubak (chuby)
 */
class PEntityList extends PComponent{

	/** @CProperty(setter="setVFields") */
	protected $visibleFields;
	/** @CProperty(setter="setOrderBy") */
	protected $orderBy;
	/** @CProperty */
	protected $oddRowsCSSClass;
	/** @CProperty */
	protected $evenRowsCSSClass;
	/** @CProperty */
	protected $headerCSSClass;
	/** @CProperty */
	protected $width;
	/** @CProperty */
	protected $style;
	/** @CProperty(setter="setEntities", getter="getEntities") */
	protected $entities;
	/** @CProperty(setter="setSessionPH") */
	protected $sessionPH;
	/** @CProperty */
	protected $translatorArray;
	/** @CProperty */
	protected $translatableFields;
	
	public static $evtOnHeaderClick = 1;
	public static $evtOnFieldClick = 2;

	private static function generateRandomString($length = 10, $letters = '1234567890qwertyuiopasdfghjklzxcvbnm'){
		$s = '';
		$lettersLength = strlen($letters)-1;

		for($i = 0 ; $i < $length ; $i++){
			$s .= $letters[rand(0, $lettersLength)];
		}

		return $s;
	}

	public function __construct($width = "100%", $id = "", $cssclass = "", $style = "", $evtslock = ""){
		$this->width = $width;
		$this->id = ($id == "") ? self::generateRandomString() : $id;
		$this->cssclazz = $cssclass;
		$this->style = $style;
		$this->eventsLock = $evtslock;
	}

	public function setVFields($fields){
		if (is_array($fields)){
			$this->visibleFields = $fields;
		}
	}
	
	public function setSessionPH($sph){
		if ($sph instanceof SessionPeaHandler){
			$this->sessionPH = $sph;
		}
	}
	
 	private function _comp($a, $b){
		return strcmp(trim($a), trim($b));
	}
	
	public function setOrderBy($fieldName){
		if (is_array($this->entities)){
			$entities2 = array();
			foreach ($this->entities as $entity){
				$setted = false;
				foreach (self::getEntityFields($entity) as $key => $value){
					$value .= "";
					if ($key == $fieldName){
						while ($entities2[$value] != null){
							$value .= " "; 
						}
						$entities2[$value] = $entity;
						$setted = true;
						break;
					}
				}
				if (!$setted) return;
			}
			if (count($entities2) > 0){
				uksort($entities2, array($this, "_comp"));
				$this->setEntities($entities2);
				$this->orderBy = $fieldName;
			}
		}
	}

	public function setEntities($entities){
		if (is_array($entities) && (count($entities) > 0) && (current($entities) instanceof Entity)){
			$this->entities = $entities;
		}
	}

	public function getEntities(){
		if (is_array($this->entities)){
			return $this->entities;
		}else{
			return null;
		}
	}
	
	private static function getEntityFields($entity){
		$res = array();
		$reflect = new ReflectionClass(get_class($entity));
		$props = $reflect->getProperties();
		for ($i = 0; $i < count($props); $i++){
			$property = $props[$i];
			$name = $property->getName();
			$res[$name] = $entity->__get($name);
		}
		return $res;
	}
	
	private static function isId($entity, $fieldName){
		$ref = new ReflectionAnnotatedProperty(get_class($entity), $fieldName);
		return $ref->hasAnnotation("Id");
	}
	
	private static function getEntityId($entity){
		foreach (self::getEntityFields($entity) as $key => $v){
			if (self::isId($entity, $key)){
				return $v;
			}
		}
		throw new ComponentException("Az egyik megjeleníteni kívánt entitás nem tartalmaz elsődleges kulcsot.");
	}
	
	private static function getEntityIdName($entity){
		foreach (self::getEntityFields($entity) as $key => $v){
			if (self::isId($entity, $key)){
				return $key;
			}
		}
		throw new ComponentException("Az egyik megjeleníteni kívánt entitás nem tartalmaz elsődleges kulcsot.");
	}
	
	public function render(){
		if ($this->id == ""){
			$this->id = self::generateRandomString();
		}
		$table = new PTable(0, 0, $this->width, $this->id, $this->cssclazz, $this->style, $this->id);
		
		// Makes the header
		$row = $table->addRow();
		//$row->id = $this->id."_header";
		$i = 0;
		foreach ($this->visibleFields as $text => $field){
			$cell = $row->addCell(null, $this->id."_header".$i++, $text);
			if ($this->headerCSSClass != ""){
				$cell->setCSSClass($this->headerCSSClass);
			}
			if ($this->isActive(self::$evtOnHeaderClick)){
				$cell->activateEvents(PCell::$evtOnClick);
				if ($this->sessionPH != null){
					$this->sessionPH->addComponent($cell);
				}
			}
		}
		
		//Makes the body
		$even = false;
		if (!is_array($this->entities)){
			return '<div class="warning">Nincsenek megjeleníthető elemek.</div>';
		}
		foreach ($this->entities as $entity){
			$even = !$even;
			$row = $table->addRow();
			$id = self::getEntityId($entity);
			//$row->id = $id;
			$j = 0;
			foreach ($this->visibleFields as $fieldName){
				$value = $entity->$fieldName;
				if (is_object($value)){
					$ref = new ReflectionClass(get_class($value));
					if ($ref->hasMethod("__toString")){
						if ($this->isActive(self::$evtOnFieldClick)){
							$cell = $row->addCell(null, $this->id."_".$id."_field".$j++, $value."");
							if (($this->evenRowsCSSClass != "") && ($this->oddRowsCSSClass != "")){
								$cell->setCSSClass($even ? $this->evenRowsCSSClass : $this->oddRowsCSSClass);
							}
							$cell->activateEvents(PCell::$evtOnClick);
							if ($this->sessionPH != null){
								$this->sessionPH->addComponent($cell);
							}
						}else{
							$cell = $row->addCell(null, "", $value."");
							if (($this->evenRowsCSSClass != "") && ($this->oddRowsCSSClass != "")){
								$cell->setCSSClass($even ? $this->evenRowsCSSClass : $this->oddRowsCSSClass);
							}
						}
					}else{
						throw new ComponentException("A megadott entitás(ok) egyik mezője olyan objektumot ".
						"tartalmaz, amit nem lehet string formátura hozni, így megjeleníteni sem.", null, 701);
					}
				}else{ 
					$valueStr = "";
					if (is_array($value)){
						foreach ($value as $k => $v){
							if (is_object($k) || is_object($v)){
								if (is_object($k)){
									$ref = new ReflectionClass(get_class($k));
									if (!$ref->hasMethod("__toString")){
										throw new ComponentException("A megadott entitás(ok) egyik mezője olyan objektumot ".
										"tartalmaz, amit nem lehet string formátura hozni, így megjeleníteni sem.", null, 701);
									}
								}
								if (is_object($v)){
									$ref = new ReflectionClass(get_class($v));
									if (!$ref->hasMethod("__toString")){
										throw new ComponentException("A megadott entitás(ok) egyik mezője olyan objektumot ".
										"tartalmaz, amit nem lehet string formátura hozni, így megjeleníteni sem.", null, 701);
									}
								}
								$valueStr .= (($valueStr == "") ? "[" : ", [").$k."] -&gt; ".$v;
								break;
							}else{
								$kk = $k;
								$vv = $v;
								if (is_array($this->translatableFields) && is_array($this->translatorArray)){
									foreach ($this->translatableFields as $tval){
										if ($tval == $fieldName){
											foreach ($this->translatorArray as $tk => $tv){
												if ($tk == $k){
													$kk = $tv;
												}
												if ($tk == $v){
													$vv = $tv;
												}
											}
										}
									}
								}
								$valueStr .= (($valueStr == "") ? "[" : ", [").$kk."] -&gt; ".$vv;
							}
						}
					}else{
						$vv = "";
						if (is_array($this->translatableFields) && is_array($this->translatorArray)){
							foreach ($this->translatableFields as $tval){
								if ($tval == $fieldName){
									foreach ($this->translatorArray as $tk => $tv){
										if ($tk == $value){
											$vv = $tv;
											break;
										}
									}
								}
							}
						}
						$valueStr = (($vv == "") ? $value."" : $vv);
					}
					if ($this->isActive(self::$evtOnFieldClick)){
						$cell = $row->addCell(null, $this->id."_".$id."_field".$j++, $valueStr);
						$cell->activateEvents(PCell::$evtOnClick);
						if (($this->evenRowsCSSClass != "") && ($this->oddRowsCSSClass != "")){
							$cell->setCSSClass($even ? $this->evenRowsCSSClass : $this->oddRowsCSSClass);
						}
						if ($this->sessionPH != null){
							$this->sessionPH->addComponent($cell);
						}
					}else{
						$cell = $row->addCell(null, "", $valueStr);
						if (($this->evenRowsCSSClass != "") && ($this->oddRowsCSSClass != "")){
							$cell->setCSSClass($even ? $this->evenRowsCSSClass : $this->oddRowsCSSClass);
						}
					}
				}
			}
		}
		
		return $table->render();
	}

	public function getEventKey(){
		return $this->id;
	}

	/** @Trigger(eventType="AjaxOnClick", senderType="PCell") */
	public function onCellClick($event){
		$sf = $event->getSendedFrom();
		$regs = array();
		if (ereg("^".$this->id."_header([0-9]+)", $sf, $regs)){
			$num = $regs[1];
			
			$i = 0;
			$fieldn = "";
			foreach ($this->visibleFields as $fieldName){
				if ($i++ == ((int) $num)){
					$fieldn = $fieldName;
					break;
				}
			}
			
			$evt = new OnEntityListHeaderClick();
			$evt->fieldName = $fieldn;
			$evt->setSender($this);
			if ($this->eventsLock != ""){
				$evt->setLock($this->eventsLock);
			}
			
			EventHandler::sendEvent($evt);
			
		}elseif (ereg("^".$this->id."_(.+)_field([0-9]+)", $sf, $regs)){
			$id = $regs[1];
			$num = $regs[2];
			
			$i = 0;
			$fieldn = "";
			foreach ($this->visibleFields as $fieldName){
				if ($i++ == ((int) $num)){
					$fieldn = $fieldName;
					break;
				}
			}
			
			$ent = null;
			
			if (current($this->entities) instanceof Entity){
				$idF = self::getEntityIdName(current($this->entities));
				foreach ($this->entities as $entity){
					if ($entity->$idF == $id){
						$ent = $entity;
						break; 
					}
				}
			}
			
			$evt2 = new OnEntityListFieldClick();
			$evt2->fieldName = $fieldn;
			$evt2->entity = $ent;
			$evt2->setSender($this);
			if ($this->eventsLock != ""){
				$evt2->setLock($this->eventsLock);
			}
			
			EventHandler::sendEvent($evt2);
		}else{
			throw new ComponentException("Nem sikerült felismerni a cellát.", null, 702);
		}
	}
	
}
?>