<?php

namespace Planaday\Html\Tags\DayParts\DayPartList;

use ArrayAccess;
use Countable;
use Exception;
use Planaday\Api\ApiException\InvalidResponseException;
use Planaday\Config\Course\CourseSettings;
use Planaday\Entities\Course\DTO\Course;
use Planaday\Entities\Course\Exception\CourseNotFoundException;
use Planaday\Entities\DayPart\DayPartController;
use Planaday\Entities\DayPart\DTO\DayPart;
use Planaday\Html\HtmlParser;
use Planaday\Html\Tags\DayParts\DayPartItem\DayPartItem;
use Planaday\Html\Tags\InvalidAttributesException;
use Planaday\Html\Tags\Tag;
use Planaday\Platform\PlatformAbstraction\LocalizationController;
use Planaday\Utility\DependencyInjection\Container;
use Planaday\Utility\DependencyInjection\InjectionImpossibleException;
use Traversable;

class DayPartList extends Tag {
	const TAG = 'day-part-list';
	const DEFAULT_TEMPLATE = 'dayPartList';
	const ID_ATTRIBUTE = 'data-id';
	const INCLUDE_E_LEARNING_DAY_PARTS_ATTRIBUTE = 'data-include-e-learning-day-parts';

	protected LocalizationController $localizationController;
	protected DayPartController $dayPartController;
	protected CourseSettings $courseSettings;

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

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

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

			$courseId = filter_var($courseIdString, FILTER_VALIDATE_INT);
			if ($courseId === false) throw new InvalidAttributesException();

			$dayParts = $this->dayPartController->getDayPartsCourse(new Course($courseId));

			if (count($dayParts) == 0){
				$this->attributes[self::TEMPLATE_ATTRIBUTE] = 'noDayPartsFoundError';
				$template = $this->getErrorTemplate();
			} else {
				$template = $this->getTemplate();
			}

			$this->initializeDayPartList($dayParts, $parser);
		}
		catch ( InvalidResponseException|InvalidAttributesException $e ) {
			$this->initializeExceptionData($e, $parser);

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

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

	/**
	 * @param ArrayAccess<int|string, DayPart>&Traversable<int|string, DayPart>&Countable $dayParts
	 * @param HtmlParser $parser
	 *
	 * @return void
	 */
	private function initializeDayPartList(ArrayAccess&Traversable&Countable $dayParts,HtmlParser $parser): void {
		$dayPartListHtml = '';

		foreach ($dayParts as $dayPart){
			if ($dayPart->isELearning() && !(($this->attributes[self::INCLUDE_E_LEARNING_DAY_PARTS_ATTRIBUTE] ?? null) == '1')){
				continue;
			}

			$dayPartListHtml .= '<pad-' . DayPartItem::TAG . ' ' . DayPartItem::ID_ATTRIBUTE . '="' . $dayPart->getId() . '"/>';
		}

		$parser->setUnsafeData('outputDayPartListItems', $dayPartListHtml);
		$parser->setData('dayPartText', $this->courseSettings->getGeneralSettings()->getDayPartText());
	}

	private function initializeExceptionData( Exception $e, HtmlParser $parser): void {
		if ($e instanceof CourseNotFoundException){
			$parser->setData('error-title', $this->localizationController->translate('Kon de cursus niet vinden'));
		}
		if ($e instanceof InvalidResponseException){
			$parser->setData('error-title', $this->localizationController->translate('Iets is mis gegaan'));
		}
		if ($e instanceof InvalidAttributesException){
			$parser->setData('error-title', $this->localizationController->translate('Dit onderdeel is helaas niet goed ingesteld, neem contact op met de website eigenaar.'));
		}

		$parser->setData('error-message', $e->getMessage() . '. Error Code: ' . $e->getCode());
	}
}