<?php
class Categoryies extends Zend_Db_Table_Abstract {
	protected $_name = 'iso_categoryies';
	protected $_primary = 'id_category';
	
	
	private $dbObject;
	private $dbObjectArray;
	
	public function init($asArray = false)
	{
		$select = $this->select()
					   	->from($this, array('id_category', 'id_parent', 'category_name', 'category_active', 'position'))
					   	->order('position ASC');
		$rows = $this->fetchAll($select);
		
		$this->dbObject = $rows;
		
		if ($asArray) {
			foreach ($rows as $i) {
				$this->dbObjectArray[$i->id_category] = $i->toArray();
			}
		}
		
	}
	
	public function getMenu($avoid = null, $contains = null)
	{
		$this->init();
		$select2 = $this->select()
					   	->from($this, array('id_parent', 'MAX(position) AS maxPosition'))
					   	->group('id_parent');
		
		$maxst = $this->fetchAll($select2);
		foreach ($maxst as $k) {
			$maxs[$k->id_parent] = $k->maxPosition;
		}
		
		$topParents = $this->getTopParents($avoid, $contains);
		
		$containsParents = null;
		if (is_array($contains) && count($contains)) {
			$containsParents = array();
			foreach ($contains as $i) {
				$helper = $this->getAllAncestors($i);
				foreach ($helper as $j) {
					if (!in_array($j, $containsParents)) {
						$containsParents[] = $j;
					}
				}
			}
		}
		
		$menu = $this->growMenu($topParents, $avoid, $containsParents);
		
		$dbInfo = array();
		foreach ($this->dbObject as $i) {
			
			$dbInfo[$i->id_category] = array(
										  'name' => $i->category_name,
										  'position' => $i->position,
										  'positionMax' => $maxs[$i->id_parent],
										  'category_active' => $i->category_active,
											);
		}
		
		$menuObject = new CategoryiesMenu($menu, $dbInfo);
		
		return $menuObject;
	}
	
	
	/**
     * Vrati strukturovane pole - celkove menu
     *
     * @param  array   $topParents  - pole idcek nejvzssich prvku v menu
     * @return array - zanorene kompletni menu
     */
	private function growMenu($topParents, $avoid = null, $contains = null)
	{
		$deepMenu = array();
		foreach ($topParents as $i) {
			
			if (!is_array($avoid) || !in_array($i, $avoid)) {
				
				if (!is_array($contains) || in_array($i, $contains)) {
					if ($children = $this->getChildren($i, $avoid)) {
		    			
						$deepMenu[$i] = $this->growMenu($children, $avoid, $contains);						
										
					} else {
						$deepMenu[$i] = array();
					}
				}
			}
			
		}
		return $deepMenu;
	}
	
	
	/**
     * Vrati pole idcek nejvyse postavenych kategorii
     * (nejvyse stojici polozky menu)
     *
     * @return array - pole ID kategorii
     */
	private function getTopParents($avoid = null, $contains = null)
	{
		$select = $this->select()
					   ->where('id_parent = 0');
					   
		if (is_array($avoid) && count($avoid)) {
			$select->where('id_category NOT IN (' . implode(',', $avoid) . ')');
		}
		$select->order('position ASC');
					   
		
		$rows = $this->fetchAll($select);
		
		$toReturn = array();
		foreach ($rows as $i) {
			
			if (is_array($contains) && count($contains)) {
				if (in_array($i->id_category, $contains)) {
					$toReturn[] = $i->id_category;
				}
			} else {
				$toReturn[] = $i->id_category;
			}
		}
		
		return $toReturn;
	}
	
	
	/**
     * Vrati pole idecek potomku polozky, false pokud zadny neni
     *
     * @param  int   $id  - id polozky 
     * @return array|bool - idcka potomku nebo false
     */
	private function getChildren($id, $avoid = null)
	{
		
		$toReturn = array();
		
		foreach ($this->dbObject as $i) {
			if ($i->id_parent == $id) {
				if (is_array($avoid)) {
					if (!in_array($i->id_category, $avoid))
						$toReturn[] = $i->id_category;
				} else {
					$toReturn[] = $i->id_category;
				}
			}
		}
		
		if (count($toReturn) == 0) return false;
		else return $toReturn;
	}
	
	public function getParentsForSelect($rootless = false, $avoid = null)
	{
		
		$menuObject = $this->getMenu($avoid);
		$tree = $menuObject->getMenuTree();
		$info = $menuObject->getCellInfo();
		
		$rows = $this->growRows($tree);

		$select = array();
		
		if ($rows) {
			
			if (!$rootless) {
				$select[0] = ' -----------';
			}
			$pref = '';
			foreach ($rows as $i) {
				$l = 1;
				$pref = '';
				while ($l < $i['deep']) {
					$pref .= '      ';
					$l++;
				}
				
				$select[$i['id']] = $pref . $info[$i['id']]['name']; 
			}
		}
		return $select;
	
		
	}
    
    private function growRows($tree, $deep = 1)
    {
    	static $rows;
        
		foreach ($tree as $k => $v) {
			$rows[] = array('id' => $k, 'deep' => $deep);
			if (count($v) > 0) {
				$this->growRows($v, $deep + 1);
			}
		}

		return $rows;     			
    }
    
    public function getPositionForInsert($idParent)
    {
    	$row = $this->fetchRow($this->select()
    								->from($this, 'MAX(position) AS maxPos')
    								->where('id_parent = ?', $idParent)
    						  );
    						  
 		if ($row) {
 			return $row->maxPos + 1;
 		} else {
 			return 0;
 		}
    }
    
    public function hasChildren($id)
    {
    	return $this->fetchAll($this->select()->where('id_parent = ?', $id))->count();
    }
	
    
    /**
     * Vrati vsechny ID potomku v jednoduchem poli
     *
     * @param  int   $id  - id rodice
     * @return array - jednoduche pole ID vsech potomku
     */
    public function getAllDescendants($id) {
    	$this->init();
    	$desc = $this->growDescendants($id);;
    	return $desc;
    }
    	
    	
	
	private function growDescendants($id)
	{
		static $descendants = array();
		$descendants[] = (int) $id;
		
		if ($children = $this->getChildren($id)) {
			foreach ($children as $i) {
				$this->growDescendants($i);
			}
		}	

		return $descendants;
	}
	
	public function repairPositions($idParent)
	{
		$rows = $this->fetchAll($this->select()->where('id_parent = ?', $idParent)->order('position ASC'));
		
		$pos = 1;
		foreach ($rows as $i) {
			if ($i->position !== $pos) {
				$i->position = $pos;
				$i->save();
			}
			
			$pos++;
		}
	}
	
	/**
     * Vrati vsechny ID predku v jednoduchem poli
     *
     * @param  int   $id  - id prvku
     * @return array - jednoduche pole ID vsech predku
     */
    public function getAllAncestors($id) {
    	
    	$this->init(true);
    	$ans = $this->_growAncestors($id);;
    	return $ans;
    }
    
    private function _growAncestors($id)
	{
		static $ancestors = array();
		$ancestors[] = (int) $id;
		
		if ($parent = $this->getParent($id, false)) {
			$this->_growAncestors($parent);
		}	

		return $ancestors;
	}
	
	public function getParent($id, $newInit = true) {
		
		if ($newInit) {
			$this->init(true);
		}
		
		$dbObjectArray = $this->dbObjectArray;
		
		if (isset($dbObjectArray[$id])) {
			return $dbObjectArray[$id]['id_parent'];
		}
		
		return 0;
	}
}
?>