<?php

namespace Planaday\Html\Tags\DayParts\DayPartItem;

use Exception;
use Planaday\Api\ApiException\InvalidResponseException;
use Planaday\Entities\DayPart\DayPartController;
use Planaday\Entities\DayPart\DTO\DayPart;
use Planaday\Entities\DayPart\Exception\DayPartNotFoundException;
use Planaday\Entities\Location\Exception\LocationNotFoundException;
use Planaday\Entities\Location\LocationController;
use Planaday\Html\HtmlParser;
use Planaday\Html\Tags\InvalidAttributesException;
use Planaday\Html\Tags\Tag;
use Planaday\Platform\PlatformAbstraction\DataHandler;
use Planaday\Platform\PlatformAbstraction\LocalizationController;
use Planaday\Utility\DependencyInjection\Container;
use Planaday\Utility\DependencyInjection\InjectionImpossibleException;

class DayPartItem extends Tag {
	const TAG = 'day-part-list-item';

	const DEFAULT_TEMPLATE = 'dayPartItem';
	const ID_ATTRIBUTE = 'data-id';
	const SHOW_E_LEARNING_ICON_ATTRIBUTE = 'data-show-e-learning-icon';
	const SHOW_LOCATION_ATTRIBUTE = 'data-show-location';
	const SHOW_DESCRIPTION_ATTRIBUTE = 'data-show-description';
	const SHOW_LABELS_ATTRIBUTE = 'data-show-labels';
	const SHOW_ICONS_ATTRIBUTE = 'data-show-icons';

	protected LocalizationController $localizationController;
	protected DayPartController $dayPartController;
	protected LocationController $locationController;
	protected DataHandler $dataHandler;

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

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

		try{
			$dayPartIdString = $this->attributes[self::ID_ATTRIBUTE] ?? null;
			if ($dayPartIdString === null) throw new InvalidAttributesException();

			$dayPartId = filter_var($dayPartIdString, FILTER_VALIDATE_INT);
			if ($dayPartId === false) throw new InvalidAttributesException();

			$dayPart = $this->dayPartController->getDayPart($dayPartId);
			$this->initializeDayPartData($dayPart, $parser);

			$template = $this->getTemplate();
		} catch (DayPartNotFoundException|InvalidResponseException|InvalidAttributesException $e){
			$this->initializeExceptionData($e, $parser);

			$template = $this->getErrorTemplate();
		}

		return $parser->parse($template);
	}

	private function initializeDayPartData(DayPart $dayPart, HtmlParser $parser): void {
		try {
			$locationId = $dayPart->getLocationIds()[0] ?? null;

			if ($locationId == null || $locationId == '' || $locationId == 0 ){
				throw new LocationNotFoundException();
			}

			$location = $this->locationController->getLocation($dayPart->getLocationIds()[0]);

			if ( $location->getCity() == '' ) {
				$parser->setData('location', $location->getName());
			} else {
				$parser->setData('location', $location->getCity());
			}
		}
		catch ( InvalidResponseException|LocationNotFoundException ) {
			$parser->setData('location', '-');
		}

		if (!$dayPart->isELearning()) {
			$parser->setData( 'startTime', $dayPart->getStartTime()->format('H:i') );
			$parser->setData( 'endTime', ($dayPart->getEndTime() ? $dayPart->getEndTime()->format('H:i') : "-"));
		}

		$parser->setData('description', $this->dataHandler->sanitizeTextareaField($dayPart->getDescription()));
		$parser->setData('labels', implode(', ', $dayPart->getLabels()));
		$parser->setData('name', $dayPart->getName());
		$parser->setData('date', $dayPart->getStartTime()->format('d-m-Y'));

		$parser->setCondition('showStartDate', $dayPart->getStartTime()->format('Y') !== '1970'); // if the daypart did not have a start date, it defaults to timestamp 0
		$parser->setCondition('isELearning', $dayPart->isELearning());
		$parser->setCondition('isNotELearning', !$dayPart->isELearning());
		$parser->setCondition('showLabels', count($dayPart->getLabels()) > 0 && (($this->attributes[self::SHOW_LABELS_ATTRIBUTE] ?? null) == '1'));
		$parser->setCondition('showELearning', (($this->attributes[self::SHOW_E_LEARNING_ICON_ATTRIBUTE] ?? null) == '1'));
		$parser->setCondition('showIcon', (($this->attributes[self::SHOW_ICONS_ATTRIBUTE] ?? null) == '1'));
		$parser->setCondition('showLocation', (($this->attributes[self::SHOW_LOCATION_ATTRIBUTE] ?? null) == '1'));
		$parser->setCondition('showDescription', (($this->attributes[self::SHOW_DESCRIPTION_ATTRIBUTE] ?? null) == '1'));
	}

	private function initializeExceptionData(Exception $exception, HtmlParser $parser): void {
		if ($exception instanceof DayPartNotFoundException){
			$parser->setData('name', $this->localizationController->translate('Kon dit dagdeel niet vinden'));
		} elseif ($exception instanceof InvalidResponseException){
			$parser->setData('name', $this->localizationController->translate('Iets is mis gegaan'));
		} elseif ($exception instanceof InvalidAttributesException){
			$parser->setData('name', $this->localizationController->translate('Dit onderdeel is helaas niet goed ingesteld, neem contact op met de website eigenaar.'));
		}
		$parser->setUnsafeData('description', substr(html_entity_decode($exception->getMessage()),0, 200));

		$parser->setCondition('showDescription', ($this->attributes[self::SHOW_DESCRIPTION_ATTRIBUTE] == '1'));
	}
}