<?php

class ContentTree {
    static $instances;
    protected $locale;

	function getCulture(){
		return $this->locale;
	}
    protected function __construct($culture)
    {
        $this->locale = $culture;
    }
    /**
     *
     * @return ContentTree
     */
    static function instance($culture = null)
    {
		if (null == $culture) {
            $culture = sfContext::getInstance()->getUser()->getCulture();
        }
        if (empty(self::$instances[$culture])) {
            self::$instances[$culture] = new ContentTree($culture);
        }
        return self::$instances[$culture];
    }

    /**
     *
     * @return sfFileCache
     */
    protected function createCacheInstance()
    {
        return new sfFileCache(array('cache_dir' => sfConfig::get('sf_cache_dir') . '/ContentTree'));
    }

    protected function getCacheKey()
    {
        return 'ContentTree.' . $this->locale;
    }

	public function clearCache()
	{
		$cache = $this->createCacheInstance();
		$cache->remove($this->getCacheKey());
		$this->root = null;
		return true;
	}

	public function clearAllCache()
	{
		foreach(sfConfig::get('app_translations_available_languages') as $locale){
			ContentTree::instance($locale)->clearCache();
		}
	}

	protected $cacheEnabled = true;

    public function setCacheEnabled($value)
    {
        $this->cacheEnabled = $value;
    }

    protected $root = null;
    protected $currentNode = null;
    function build($force = false)
    {
        $default_locale = sfConfig::get('app_translations_default_language');

        if ($force) {
            $this->clearCache();
        }
        if (empty($this->root)) {
            // printf('building tree cache...');
            $cache = $this->createCacheInstance();
            $tree = $cache->get($this->getCacheKey());
            if ($tree !== null) {
                $this->root = unserialize($tree);
            } else {
                $criteria = new Criteria();
                $criteria->addAscendingOrderByColumn(NodePeer::TREE_LEFT);
                $nodes = NodePeer::doSelectWithI18n($criteria, $default_locale);
                // var_dump($nodes);exit;
                $root = array_shift($nodes);
                if (null != $root) {
                    $parentTreeNode = new ContentTreeNode($root, null, $default_locale);
					$parentTreeNode->setOwnerTree($this);
                    $parentTreeNode->setMockTranslation($this->locale != $default_locale);
                    $this->root = $parentTreeNode;

                    $prevTreeNode = $parentTreeNode;

                    $prevNode = $root;
                    $nodeStack = array();
                    $nodeStack[] = $root;
                    $stack = array();
                    $stack[] = $parentTreeNode;
                    foreach($nodes as $node) {
                        $treeNode = new ContentTreeNode($node, $parentTreeNode, $default_locale);
						$treeNode->setOwnerTree($this);
                        $treeNode->setMockTranslation($this->locale != $default_locale);
                        if ($prevNode->getTreeParent() == $node->getTreeParent()) {
                            // printf('1. [%d, %d, %d]<br />', $node->getId(), $node->getTreeLeft(), $node->getTreeRight());
                        } else {
                            if ($prevNode->getId() == $node->getTreeParent()) {
                                // printf('2. [%d, %d, %d]<br />', $node->getId(), $node->getTreeLeft(), $node->getTreeRight());
                                $stack[] = $parentTreeNode;
                                $nodeStack[] = $prevNode;
                                $parentTreeNode = $prevTreeNode;
                            } else {
                                // printf('3. [%d, %d, %d]<br />', $node->getId(), $node->getTreeLeft(), $node->getTreeRight());
                                while (count($nodeStack) > 0 && ($node->getTreeParent() != $nodeStack[count($nodeStack) - 1]->getId())) {
                                    $parentTreeNode = array_pop($stack);
                                    array_pop($nodeStack);
                                }
                            }
                        }
                        $parentTreeNode->addChild($treeNode);
                        $prevTreeNode = $treeNode;
                        $prevNode = $node;
                    }
                }
                unset($nodes);
                unset($stack);
                unset($prevNode);
                unset($prevTreeNode);
                unset($parentTreeNode);
                unset($nodeStack);
                unset($treeNode);
                if ($this->locale != $default_locale) {
                    $localized_nodes = array();
                    $criteria = new Criteria();
                    $criteria->addAscendingOrderByColumn(NodePeer::TREE_LEFT);
                    $nodes = NodePeer::doSelectWithI18n($criteria, $this->locale);
                    foreach($nodes as /*(Node)*/$node) {
                        $ContentTreeNode = $this->getContentTreeNodeById($node->getId());
                        if ($ContentTreeNode) {
                        	$ContentTreeNode->setTitle($node->getTitle());
                        	$ContentTreeNode->setMenuTitle($node->getMenuTitle());
                        	$ContentTreeNode->setSubTitle($node->getSubTitle());
                        	$ContentTreeNode->setUrlIdentifier($node->getUrlIdentifier());
                        	$ContentTreeNode->setBrowserTitleType($node->getBrowserTitleType());
                        	$ContentTreeNode->setBrowserTitleContent($node->getBrowserTitleContent());
                        	$ContentTreeNode->setSeoKeywordsType($node->getSeoKeywordsType());
                        	$ContentTreeNode->setSeoKeywordsContent($node->getSeoKeywordsContent());
                        	$ContentTreeNode->setSeoDescriptionContent($node->getSeoDescriptionContent());
                        	$ContentTreeNode->setSeoDescriptionType($node->getSeoDescriptionType());
                        	$ContentTreeNode->setCulture($this->locale);
                        	$ContentTreeNode->setMockTranslation(false);
                        }

                        //var_dump($ContentTreeNode);                        exit;
                    }
                    //var_dump($this);                    exit;
                }
                if ($this->cacheEnabled) {
                    $cache->set($this->getCacheKey(), serialize($this->root));
                }
            }
            unset($tree);
        }
    }

    function initializeCurrentNodeByPath($path)
    {
        $path = explode('/', $path);
		while (count($path) > 0 && empty($path[0])) {
            array_shift($path);
        }
		// var_dump($path);exit;
        $result = $this->getRoot();
        while (($result != null) && count($path) > 0) {
            $result->active = true;
            $pathItem = array_shift($path);
            // var_dump($pathItem);
            $result = $result->getChildByUrlIdentifier($pathItem);
        }
        if ($result != null) {
            $result->active = true;
        }
		$this->currentNode = $result;
        return $result;
    }

    function initializeCurrentNodeById($id)
    {
        $result = $this->getContentTreeNodeById($id);
        $node = $result;
        while (isset($node)) {
            $node->active = true;
            $node = $node->parent;
        }
        $this->currentNode = $result;
        return $result;
    }

    function initializeCurrentNode($ContentTreeNode)
    {
		$result = $ContentTreeNode;
        $node = $result;
        while (isset($node)) {
            $node->active = true;
            $node = $node->parent;
        }
        $this->currentNode = $result;
        return $result;
    }

    /**
     *
     * @return ContentTreeNode
     */
    function getRoot()
    {
        return $this->root;
    }

    /**
     * @return ContentTreeNode
     */
	function getCurrentNode()
    {
        return $this->currentNode;
    }
    // function getContentNodeByUrl($url)
    // {
    // $path = explode('/', $url);
    // if (empty($path[0])) {
    // array_shift($path);
    // }
    // $result = $this->getRoot();
    // while (($result != null) && count($path) > 0) {
    // $pathItem = array_shift($path);
    // // var_dump($pathItem);
    // $result = $result->getChildByUrlIdentifier($pathItem);
    // }
    // //var_dump($result);exit;
    // return $result;
    // }
    /**
     *
     * @return ContentTreeNode
     */
    function getContentTreeNodeById($id)
    {
		if(!$this->getRoot()){
			$this->build();
		}
    	assert($this->getRoot());
        return $this->getRoot()->getContentTreeNodeById($id);
    }

    protected function debugChildren($nodes, $prefix = '')
    {
        foreach($nodes as $node) {
            echo $prefix . $node->getTitle() . '-' . $node->getUrl() . '<br />';
            if (count($node->children) > 0) {
                $this->debugChildren($node->children, $prefix . '+');
            }
        }
    }

    function dump()
    {
        $this->debugChildren(array($this->getRoot()));
    }

	function getAll(){
		return array_merge(array($this->getRoot()), $this->getRoot()->getAll());
	}

	public function initializeCurrentNodeByReferer($request)
	{

		//var_dump(sprintf('%s/%s', sfConfig::get('app_static_url', sfConfig::get('app_site_url')), $this->getUser()->getCulture()));exit;
		$urlPrefix = sprintf('%s/%s', sfConfig::get('app_static_url', sfConfig::get('app_site_url')), sfContext::getInstance()->getUser()->getCulture());
		//var_dump($urlPrefix);
		$shortPath = str_replace($urlPrefix, '', $request->getReferer());
		//var_dump($shortPath);
		return $this->initializeCurrentNodeByPath($shortPath);


	}
}

?>