<?php
/**
 * Šablona XML elementu pro exporty.
 *
 * @category Dalten
 * @package  Xml
 */
class Dalten_Xml_Template_Element extends Dalten_Xml_Template_Node
{
	protected $_children = array();
	protected $_attributes = array();
	protected $_forcedPresence = false;
	protected $_showWhenFilled = array();

	/**
	 * Přidá element-potomka.
	 *
	 * @param string      $name         Jméno elementu-potomka.
	 * @param string|null $variableName Pokud je vyplněno, proměnná kterou se později potomek vyplní.
	 *
	 * @return Dalten_Xml_Template_Element Nově vytvořený potomek.
	 */
	public function addElement($name, $variableName = null)
	{
		$child = new Dalten_Xml_Template_Element($name);

		if ($variableName) {
			$child->setVariable($variableName);
		}

		$this->_children[] = $child;
		return $child;
	}

	/**
	 * Podsune vlastní instanci elementu jako potomka.
	 *
	 * @param Dalten_Xml_Template_Element $instance Instance potomka.
	 *
	 * @return Dalten_Xml_Template_Element Podsunutá instance.
	 */
	public function pushElement(Dalten_Xml_Template_Element $instance) {
		$this->_children[] = $instance;
		return $instance;
	}

	/**
	 * Přidá šablonu atributu.
	 *
	 * @param string      $name         Jméno atributu.
	 * @param string|null $variableName Pokud je vyplněno, proměnná kterou se později atribut vyplní.
	 *
	 * @return Dalten_Xml_Template_Attribute Nově vytvořený atribut.
	 */
	public function addAttribute($name, $variableName=null)
	{
		$attribute = new Dalten_Xml_Template_Attribute($name);

		if ($variableName) {
			$attribute->setVariable($variableName);
		}

		$this->_attributes[] = $attribute;
		return $attribute;
	}

	/**
	 * Přidá nový element typu {@link Dalten_Xml_Template_Opt Opt}.
	 *
	 * @param string $name         Jméno elementu-potomka.
	 * @param string $variableName Pokud je vyplněno, proměnná kterou se později potomek vyplní.
	 *
	 * @return Dalten_Xml_Template_Opt Nový opt uzel.
	 */
	public function addOpt($name, $variableName)
	{
		$Opt= new Dalten_Xml_Template_Opt($name);
		$Opt->setVariable($variableName);
		$this->_children[] = $Opt;
		return $Opt;
	}

	/**
	 * {@inheritdoc}
	 */
	public function fill(SimpleXMLElement $rootElement, array $data)
	{
		if (!$this->_checkWhenFilled($data)) {
			return null;
		}

		if (
			$this->_hasNoChild() &&
			$this->_hasEmptyValue($data) &&
			!$this->_forcedPresence
		) {
			return null; // nenecháváme prázdné elementy
		}

		$childElement = $rootElement->addChild($this->_name);

		if ($this->_variableName) {
			if (isset($data[$this->_variableName])) {
				$text = new DOMText($this->_guardFloatIfNeeded($data[$this->_variableName]));
				dom_import_simplexml($childElement)->appendChild($text);
			}
		}

		foreach ($this->_attributes as $attribute) {
			/**  @var $attribute Dalten_Xml_Template_Attribute */
			$attribute->fill($childElement, $data);
		}

		foreach ($this->_children as $child) {
			/** @var $child Dalten_Xml_Template_Element */
			$child->fill($childElement, $data);
		}
		return $childElement;
	}

	/**
	 * {@inheritdoc}
	 */
	public function verify(array $data)
	{
		$errors = parent::verify($data);
		foreach ($this->_children as $child) {
			/** @var $child Dalten_Xml_Template_Node */
			$localErr = $child->verify($data);
			$errors = array_merge($errors, $localErr);
		}
		foreach ($this->_attributes as $attr) {
			/** @var $attr Dalten_Xml_Template_Node */
			$localErr = $attr->verify($data);
			$errors = array_merge($errors, $localErr);
		}
		return $errors;
	}


	/**
	 * Vrací, zda je element bez potomků.
	 *
	 * @return bool Je element bez potomků?
	 */
	protected function _hasNoChild()
	{
		return (
			(count($this->_children)==0) &&
			(count($this->_attributes)==0)
		);
	}

	/**
	 * Zkontroluje, zda jsou nastavená všechna vyjmenovaná pole.
	 *
	 * @param array $data Pole vstupních dat.
	 *
	 * @return bool Jsou nastavená všechna vyjmenovaná pole?
	 */
	protected function _checkWhenFilled(array $data)
	{
		foreach ($this->_showWhenFilled as $key) {
			if (empty($data[$key])) {
				return false;
			}
 		}
		return true;
	}

	/**
	 * Nastaví element aby se neskrýval pokud je prázdný.
	 *
	 * @return Dalten_Xml_Template_Element Fluent interface.
	 */
	public function forcedPresence()
	{
		$this->_forcedPresence = true;
		return $this;
	}

	/**
	 * Vyplní tento element a jeho potomky pouze tehdy, když jsou zadaná pole v datech vyplněna.
	 *
	 * @param array $fields Sezname názvů polí, proti kterých chceme kontrolovat.
	 *
	 * @return Dalten_Xml_Template_Element Fluent interface.
	 */
	public function showWhenFilled(array $fields)
	{
		$this->_showWhenFilled = $fields;
		return $this;
	}
}
