<?php

namespace Engine\RemoteData\InfoBox;

abstract class ContainerAbstract
{

	/**
	 * Container title
	 * @var string
	 */
	protected $title;

	/**
	 * A unique code of the current container.
	 * @var string
	 */
	protected $code;

	/**
	 * The containers and fields.
	 * @var array
	 */
	protected $children = [];

	final public function __construct($title=null, $code=null)
	{
		$this->setTitle($title);
		$this->code = $code;
	}


	/**
	 * Creates a new container (faster instantiation).
	 * @param String $title
	 * @param String $code
	 */
	static public function create($title=null, $code=null)
	{
		return new static($title, $code);
	}

	public function setTitle($title)
	{
		$this->title = $title;
		return $this;
	}

	public function getCode()
	{
		return $this->code;
	}

	/**
	 * @param \Engine\RemoteData\InfoBox\IconAbstract $icon
	 * @param integer $index
	 * - If $index is positive then the icon is inserted at that offset from the beginning of the children array.
	 * - If $index is negative then the icon is inserted at that offset from the end of the children array.
	 * @return \Engine\RemoteData\InfoBox\ContainerAbstract
	 */
	public function addIcon(\Engine\RemoteData\InfoBox\IconAbstract $icon, $index=null)
	{
		if ($index!==null) {
			array_splice($this->children, $index, 0, [$icon]);
		}
		else {
			$this->children[] = $icon;
		}
		return $this;
	}

	/**
	 * @param \Engine\RemoteData\InfoBox\FieldAbstract $field
	 * @param integer $index
	 * - If $index is positive then the field is inserted at that offset from the beginning of the children array.
	 * - If $index is negative then the field is inserted at that offset from the end of the children array.
	 * @return \Engine\RemoteData\InfoBox\ContainerAbstract
	 */
	public function addField(\Engine\RemoteData\InfoBox\FieldAbstract $field, $index=null)
	{
		if ($index!==null) {
			array_splice($this->children, $index, 0, [$field]);
		}
		else {
			$this->children[] = $field;
		}
		return $this;
	}

	/**
	 * @param \Engine\RemoteData\InfoBox\ContainerAbstract $container
	 * @param integer $index
	 * - If $index is positive then the container is inserted at that offset from the beginning of the children array.
	 * - If $index is negative then the container is inserted at that offset from the end of the children array.
	 * @return \Engine\RemoteData\InfoBox\ContainerAbstract
	 */
	public function addContainer(\Engine\RemoteData\InfoBox\ContainerAbstract $container, $index=null)
	{
		if ($index!==null) {
			array_splice($this->children, $index, 0, [$container]);
		}
		else {
			$this->children[] = $container;
		}
		return $this;
	}

	abstract public function exportAsArray();

	abstract public function exportAsStdObj();


	public function getChildren()
	{
		return  $this->children;
	}

	/**
	 * Recursively searches for a container by its code.
	 * @param string $code
	 * @return ?\Engine\RemoteData\InfoBox\ContainerAbstract
	 */
	public function getContainerByCode($code) :?\Engine\RemoteData\InfoBox\ContainerAbstract
	{

		foreach($this->children as $childObj) {
			if ($childObj instanceof \Engine\RemoteData\InfoBox\ContainerAbstract) {
				if ($childObj->getCode()==$code) {
					return $childObj;
				} else {
					$foundContainer = $childObj->getContainerByCode($code);
					if ($foundContainer) {
						return $foundContainer;
					}
				}
			}
		}
		return null;

	}

}