<?php

namespace Planaday\Html\Tags\Form\CourseSearch\LocationSelect;

use ArrayAccess;
use Countable;
use Exception;
use Planaday\Api\ApiException\InvalidResponseException;
use Planaday\Entities\Course\PostRequest\CourseSearchFieldEnum;
use Planaday\Entities\Location\DTO\Location;
use Planaday\Entities\Location\Exception\LocationNotFoundException;
use Planaday\Entities\Location\LocationController;
use Planaday\Html\HtmlParser;
use Planaday\Html\Tags\Form\GenericInput\CheckboxInput\CheckboxInput;
use Planaday\Html\Tags\Form\SelectableDataInputFieldTag;
use Planaday\Html\Tags\Tag;
use Planaday\Platform\PlatformAbstraction\LocalizationController;
use Planaday\Utility\DependencyInjection\Container;
use Planaday\Utility\DependencyInjection\InjectionImpossibleException;
use Traversable;

class LocationSelect extends Tag {
	const TAG = 'location-select';
	const DEFAULT_TEMPLATE = 'locationSelect';

	protected LocationController $locationController;
	protected LocalizationController $localization;
	/**
	 * @param Container $registry
	 *
	 * @throws InjectionImpossibleException
	 */
	public function __construct(Container $registry ) {
		$this->locationController = $registry->getInstance(LocationController::class);
		$this->localization = $registry->getInstance(LocalizationController::class);
		parent::__construct( __DIR__, self::DEFAULT_TEMPLATE, $registry );
	}

	public function buildTag(): string {
		$parser = $this->getNewParser();

		try {
			$locations = $this->locationController->getAllDB();

			if (count($locations) == 0){
				throw new LocationNotFoundException();
			}

			$parser->setUnsafeData('locationSelections', $this->buildInputFieldHtml($locations));
			$parser->injectAttribute(
				$this->getRecursiveVersionOfAttribute(SelectableDataInputFieldTag::FIELD_CLASS_ATTRIBUTE),
				CourseSearchFieldEnum::class
			);

			return $parser->parse($this->getTemplate());
		}
		catch (Exception $e){
			$this->initializeExceptionData($e, $parser);
			return $parser->parse($this->getErrorTemplate());
		}
	}

	/**
	 * @param ArrayAccess<int|string, Location>&Traversable<int|string, Location>&Countable $locations
	 *
	 * @return string
	 */
	private function buildInputFieldHtml(ArrayAccess&Traversable&Countable $locations):string {
		$inputFields = [];

		foreach ($locations as $location){
			$city = $location->getCity();

			if (!array_key_exists($city, $inputFields)){
				$inputFields[$city] = [];
			}

			$inputFields[$city][] = $location;
		}

		$inputFieldHtml = '';

		$postField = CourseSearchFieldEnum::LOCATIONS;

		foreach ($inputFields as $field){
			$city = $field[0]->getCity();

			if ( $city === '' ){
				$city = $this->localization->translate('Geen stad');
			}

			if (count($field) > 1){
				$inputFieldHtml .= CheckboxInput::getTagHtml($postField, $city, $city, '');

				foreach ($field as $location){
					$locationTitle = $location->getCity() . ', ' .
					                 $location->getStreet1() . ' ' .
					                 $location->getHouseNumber() . $location->getHouseNumberExtension() . ', ' .
					                 $location->getZipcode();

					$inputFieldHtml .= CheckboxInput::getTagHtml($postField, $location->getName(), $locationTitle, '' . $location->getId());
					$inputFieldHtml .= CheckboxInput::getClosingTagHtml();
				}
			}
			else {
				$locationTitle = $field[0]->getCity() . ', ' .
				                 $field[0]->getStreet1() . ' ' .
				                 $field[0]->getHouseNumber() . $field[0]->getHouseNumberExtension() . ', ' .
				                 $field[0]->getZipcode();

				$inputFieldHtml .= CheckboxInput::getTagHtml($postField, $city, $locationTitle, '' . $field[0]->getId());
			}

			$inputFieldHtml .= CheckboxInput::getClosingTagHtml();
		}

		return $inputFieldHtml;
	}

	private function initializeExceptionData( Exception $e, HtmlParser $parser): void {
		if ($e instanceof InvalidResponseException){
			$parser->setData('error-title', $this->localization->translate('Iets is mis gegaan'));
		}
		$parser->setData('error-message', $e->getMessage() . '. Error Code: ' . $e->getCode());
	}
}