<?php

/**
 * Extend Finder Visitor
 *
 * @package Less
 * @subpackage visitor
 */
class Less_Visitor_extendFinder extends Less_Visitor{

	public $contexts = array();
	public $allExtendsStack;
	public $foundExtends;

	public function __construct(){
		$this->contexts = array();
		$this->allExtendsStack = array(array());
		parent::__construct();
	}

	/**
	 * @param Less_Tree_Ruleset $root
	 */
    public function run($root){
		$root = $this->visitObj($root);
		$root->allExtends =& $this->allExtendsStack[0];
		return $root;
	}

    public function visitRule($ruleNode, &$visitDeeper ){
		$visitDeeper = false;
	}

    public function visitMixinDefinition( $mixinDefinitionNode, &$visitDeeper ){
		$visitDeeper = false;
	}

    public function visitRuleset($rulesetNode){

		if( $rulesetNode->root ){
			return;
		}

		$allSelectorsExtendList = array();

		// get &:extend(.a); rules which apply to all selectors in this ruleset
		if( $rulesetNode->rules ){
			foreach($rulesetNode->rules as $rule){
				if( $rule instanceof Less_Tree_Extend ){
					$allSelectorsExtendList[] = $rule;
					$rulesetNode->extendOnEveryPath = true;
				}
			}
		}


		// now find every selector and apply the extends that apply to all extends
		// and the ones which apply to an individual extend
		foreach($rulesetNode->paths as $selectorPath){
			$selector = end($selectorPath);

			$j = 0;
			foreach($selector->extendList as $extend){
				$this->allExtendsStackPush($rulesetNode, $selectorPath, $extend, $j);
			}
			foreach($allSelectorsExtendList as $extend){
				$this->allExtendsStackPush($rulesetNode, $selectorPath, $extend, $j);
			}
		}

		$this->contexts[] = $rulesetNode->selectors;
	}

    public function allExtendsStackPush($rulesetNode, $selectorPath, $extend, &$j){
		$this->foundExtends = true;
		$extend = clone $extend;
		$extend->findSelfSelectors( $selectorPath );
		$extend->ruleset = $rulesetNode;
		if( $j === 0 ){
			$extend->firstExtendOnThisSelectorPath = true;
		}

		$end_key = count($this->allExtendsStack)-1;
		$this->allExtendsStack[$end_key][] = $extend;
		$j++;
	}


    public function visitRulesetOut( $rulesetNode ){
		if( !is_object($rulesetNode) || !$rulesetNode->root ){
			array_pop($this->contexts);
		}
	}

    public function visitMedia( $mediaNode ){
		$mediaNode->allExtends = array();
		$this->allExtendsStack[] =& $mediaNode->allExtends;
	}

    public function visitMediaOut(){
		array_pop($this->allExtendsStack);
	}

    public function visitDirective( $directiveNode ){
		$directiveNode->allExtends = array();
		$this->allExtendsStack[] =& $directiveNode->allExtends;
	}

    public function visitDirectiveOut(){
		array_pop($this->allExtendsStack);
	}
}


