<?php
/*
 * Copyright (c) 2013, webvariants GbR, http://www.webvariants.de
 *
 * This file is released under the terms of the MIT license. You can find the
 * complete text in the attached LICENSE file or online at:
 *
 * http://www.opensource.org/licenses/mit-license.php
 */

class WV_Form_Multiple extends sly_Form_ElementBase implements sly_Form_IElement {
	protected $data;
	protected $elements;

	/**
	 * Constructor
	 *
	 * @param string $name   element name
	 * @param string $label  the label
	 * @param array  $data   data for all enclosed elements
	 * @param string $id     optional ID (if not given, the name is used)
	 */
	public function __construct($name, $label, $data, $id = null) {
		parent::__construct($name, $label, '', $id);

		$this->data     = $data;
		$this->elements = array();

		$this->addOuterClass('wv-form-multiple-row');
	}

	public function add(sly_Form_IElement $element) {
		$this->elements[] = $element;
		return $this;
	}

	public function clear() {
		$this->elements = array();
		return $this;
	}

	/**
	 * Renders the element
	 *
	 * This method renders the form element and returns its XHTML code.
	 *
	 * @return string  the XHTML code
	 */
	public function render() {
		if (empty($this->elements)) {
			throw new Exception('No child elements added.');
		}

		$base = sly_Util_AddOn::assetBaseUri('webvariants/developer-utils');
		sly_Core::getLayout()->addJavaScriptFile($base.'js/multi-input.js');

		return $this->renderFilename('multiple-element.phtml');
	}

	protected function getViewFile($file) {
		$full = DEVUTILS_PATH.'/views/'.$file;
		if (file_exists($full)) return $full;

		throw new sly_Form_Exception(t('view_not_found', $file));
	}

	protected function renameElements($rowIdx) {
		foreach ($this->elements as $element) {
			$elName  = $element->getName();
			$elID    = $element->getID();
			$name    = $this->getName().'['.$rowIdx.']['.$elName.']';
			$id      = $this->getID().'_'.$rowIdx.'_'.$elID;

			if (!isset($element->origName)) {
				$element->origName = $elName;
				$element->origID   = $elID;

				$element->setAttribute('data-origname', $elName);
			}

			$element->setName($name);
			$element->setID($id);
		}
	}

	protected function revertElements() {
		foreach ($this->elements as $element) {
			$element->setName($element->origName);
			$element->setID($element->origID);

			unset($element->origName, $element->origID);
		}
	}

	/**
	 * Returns the value to be displayed
	 *
	 * This method will return the values that shall be displayed in the form.
	 * This is mostly useful when a form is submitted and the POST data will be
	 * shown instead of those that were given when the form elements are
	 * initialized.
	 *
	 * @return array  element data [{element: displayValue, element2: displayValue2, ...}, {element: displayValue}, ...]
	 */
	public function getDisplayValue($collectRenderOutput = false) {
		$isPOST   = $_SERVER['REQUEST_METHOD'] === 'POST';
		$name     = $this->getName();
		$formData = $isPOST ? (isset($_POST[$name]) && is_array($_POST[$name]) ? array_values($_POST[$name]) : array()) : $this->data;
		$result   = array();

		if (!$isPOST && empty($formData)) {
			$formData = array(array());
		}

		for ($i = 0; $i < count($formData); ++$i) {
			$rowData = array();
			$this->renameElements($i);

			foreach ($this->elements as $element) {
				$name = $element->origName;

				if (isset($formData[$i][$name])) {
					if ($element instanceof sly_Form_Input_Boolean) {
						$element->setChecked();
					}
					elseif ($element instanceof sly_Form_Select_Base) {
						$element->setSelected($formData[$i][$name]);
					}
					else {
						$element->setValue($formData[$i][$name]);
					}
				}
				else {
					if ($element instanceof sly_Form_Input_Boolean) {
						$element->setChecked(false);
					}
				}

				$rowData[$name] = $collectRenderOutput ? $element->render() : $element->getDisplayValue();
			}

			$this->revertElements();
			$result[] = $rowData;
		}

		return $result;
	}

	public function setValue($value) {
		$this->data = $value;
	}
}
