<?php

namespace Planaday\Html\Tags\Form;

use ArrayAccess;
use Planaday\Entities\PostEntities;
use Planaday\Html\HtmlParser;
use Planaday\Html\Tags\Tag;
use Planaday\Platform\PlatformAbstraction\DataHandler;
use Planaday\Utility\DataGrouping\ArrayWalker;
use Planaday\Utility\DependencyInjection\Container;
use Planaday\Utility\DependencyInjection\InjectionImpossibleException;
use Planaday\Utility\PluginData;
use Traversable;

abstract class DataInputFieldTag extends Tag {
	const FIELD_NAME_ARRAY_NAME = 'data-field-name-array';
	const FIELD_NAME_ARRAY_INDEX = 'data-field-name-array-index';
	protected string $fieldName;

	protected PostEntities $postEntities;
	protected ArrayWalker $arrayWalker;
	protected DataHandler $dataHandler;
	protected PluginData $pluginData;

	/**
	 * @param string $TAG_DIR
	 * @param string $DEFAULT_TEMPLATE
	 * @param Container $registry
	 *
	 * @throws InjectionImpossibleException
	 */
	protected function __construct(string $TAG_DIR, string $DEFAULT_TEMPLATE, Container $registry) {
		$this->postEntities = $registry->getInstance(PostEntities::class);
		$this->arrayWalker  = $registry->getInstance(ArrayWalker::class);
		$this->dataHandler  = $registry->getInstance(DataHandler::class);
		$this->pluginData   = $registry->getInstance(PluginData::class);

		parent::__construct($TAG_DIR, $DEFAULT_TEMPLATE, $registry);
	}

	protected function getNewParser(): HtmlParser {
		$parser = parent::getNewParser();

		$parser->injectAttribute(
			$this->getRecursiveVersionOfAttribute(self::FIELD_NAME_ARRAY_NAME),
			$this->getFullFieldName()
		);
		$parser->injectAttribute(
			$this->getRecursiveVersionOfAttribute(self::FIELD_NAME_ARRAY_INDEX),
			null
		);


		if ($this->getFieldErrors() != null){
			$errors = $this->getErrorMessage();
			$parser->setCondition('hasErrors', true);
			$parser->setUnsafeData('error-message', $errors);
			$parser->setData('error-class', 'pad-form-error');
		} else {
			$parser->setCondition('hasErrors', false);
		}

		$parser->setData('field-id-name', $this->fieldName ?? '');
		$parser->setData('field-name', $this->getFullFieldName());
		$currentValue = $this->getCurrentFieldValue();
		if(is_float($currentValue) || is_string($currentValue) || is_int($currentValue) || is_null($currentValue) )
			$parser->setData('field-value', $currentValue);

		return $parser;
	}

	protected function getErrorMessage(int $maxDepth = -1):?string {
		$errors = $this->getFieldErrors();
		if ($errors === null) return null;

		$errorMessage = '';

		if (is_array($errors) || $errors instanceof Traversable ){
			$errors = $this->arrayWalker->getAsFlatArray($errors, '' ,$maxDepth);
		} else {
			$errors = [$errors];
		}
		foreach ($errors as $error){
			if ($error) $errorMessage .= '<li>' . htmlspecialchars($error) . '</li>';
		}

		return $errorMessage;
	}

	protected function getFullFieldName(): string{
		return $this->getNextFieldNameArray($this->fieldName ?? '');
	}

	protected function getNextFieldNameArray(?string $arrayName = null): string{
		if (isset($this->attributes[self::FIELD_NAME_ARRAY_NAME])){
			$return = $this->attributes[self::FIELD_NAME_ARRAY_NAME];

			if (isset($this->attributes[self::FIELD_NAME_ARRAY_INDEX])){
				$return .= '[' . $this->attributes[self::FIELD_NAME_ARRAY_INDEX] . ']';
			}

			$return .= ($arrayName != null) ? '[' . $arrayName . ']':'';
			return $return;
		}

		if ($arrayName !== null) {
			if (PostEntities::is($arrayName)) return $this->pluginData->getFullPrefix() . $arrayName;
			$arrayName = '[' . $arrayName . ']';
		}

		return $this->pluginData->getFullPrefix() . PostEntities::GENERIC_POST . ($arrayName ?? '');
	}

	protected function getCurrentFieldValue(): mixed {
		$fieldName = $this->getFullFieldName();
		$postData = $this->dataHandler->getPostData();

		return $this->arrayWalker->walk($fieldName, $postData);
	}

	protected function getFieldErrors(): ArrayAccess|array|string|null{
		$fieldName = $this->getFullFieldName();
		$errors = $this->postEntities->getPostErrors();

		return $this->arrayWalker->walk($fieldName, $errors);
	}
}