<?php

namespace Planaday\Html\Tags\Course\CourseShortcode;

use Exception;
use Planaday\Api\ApiException\InvalidResponseException;
use Planaday\Config\Course\CourseSettings;
use Planaday\Entities\CostDataUtility;
use Planaday\Entities\Course\CourseController;
use Planaday\Entities\Course\CourseUtility;
use Planaday\Entities\Course\DTO\Course;
use Planaday\Entities\Course\Exception\CourseNotFoundException;
use Planaday\Entities\DayPart\DayPartController;
use Planaday\Html\HtmlParser;
use Planaday\Html\Tags\DayParts\DayPartItem\DayPartItem;
use Planaday\Html\Tags\DayParts\DayPartList\DayPartList;
use Planaday\Html\Tags\Tag;
use Planaday\Platform\PlatformAbstraction\LocalizationController;
use Planaday\Platform\PlatformAbstraction\UrlHandler;
use Planaday\Utility\DependencyInjection\Container;
use Planaday\Utility\DependencyInjection\InjectionImpossibleException;
use Planaday\Utility\GeneralTermEnum;
use Planaday\Utility\PluginData;

class CourseShortcode extends Tag {
	const TAG = 'course';
	const DEFAULT_TEMPLATE = 'course';


	protected LocalizationController $localizationController;
	protected DayPartController $dayPartController;
	protected CourseController $courseController;
	protected CostDataUtility $costUtility;
	protected CourseUtility $courseUtility;
	protected UrlHandler $urlHandler;
	protected CourseSettings $courseSettings;
	protected PluginData $pluginData;

	/**
	 * @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);
		$this->courseController = $registry->getInstance(CourseController::class);
		$this->costUtility = $registry->getInstance(CostDataUtility::class);
		$this->courseUtility = $registry->getInstance(CourseUtility::class);
		$this->urlHandler = $registry->getInstance(UrlHandler::class);
		$this->pluginData = $registry->getInstance(PluginData::class);
		parent::__construct(__DIR__, self::DEFAULT_TEMPLATE, $registry);
	}

	public function buildTag(): string {
		$parser = $this->getNewParser();
		$courseIdString = $this->urlHandler->getUrlQueryField($this->pluginData->getShortPrefix() . GeneralTermEnum::COURSE_ID_URL_QUERY);

		$courseId = filter_var($courseIdString ?? 'false', FILTER_VALIDATE_INT);

		if (!isset($courseIdString) || $courseId === false) {
			$this->attributes[self::TEMPLATE_ATTRIBUTE] = 'noCourseMessage';
			return $parser->parse($this->getErrorTemplate());
		}

		try {
			$course = $this->courseController->getCourse($courseId, true);
			$this->initializeCourseData($course, $parser);
			$template = $this->getTemplate();
		}
		catch(CourseNotFoundException|InvalidResponseException $e){
			$this->initializeExceptionData($e, $parser);
			$this->attributes[self::TEMPLATE_ATTRIBUTE] = 'dataErrorMessage';
			$template = $this->getErrorTemplate();
		}

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

	private function initializeCourseData(Course $course, HtmlParser $parser): void {
		$generalSettings = $this->courseSettings->getGeneralSettings();
		$detailSettings = $this->courseSettings->getDetailSettings();

		if (!($course->getDayPartAmount() == 1 && $course->isHasELearning())){
			$parser->setCondition('showDayPartWarning', $course->hasPastDayParts($generalSettings->isELearningCountsAsStart()));
		}

		$availableSpots = $course->getUsersData()->getAvailableSpots($generalSettings->isIncludeOptionInCount());
		$courseLabels = $course->getLabels();
		$description = $course->getDescription();

		$parser->setUnsafeData('description', $description);
		$parser->setUnsafeData('costRemark', $course->getCostsData()->getRemark());

		$showBothPrices = $detailSettings->isShowPriceWithAndWithoutTax();
		$parser->setData('price', $this->costUtility->getPriceString($course->getCostsData(), $showBothPrices));

		$parser->setData('dayPartText', $this->courseSettings->getGeneralSettings()->getDayPartText());
		$parser->setData('courseName', $course->getName());
		$parser->setData('availableSpots', $availableSpots);
		$parser->setData('level', $course->getLevel());
		$parser->setData('dayPartCount', $this->courseUtility->getDayPartCount($course, $detailSettings->isIncludeELearningDayParts()));
		$parser->setData('labels', implode(', ', $courseLabels));
		$parser->setData('courseId', $course->getId());

		$parser->setCondition('courseFull', $availableSpots <= 0);
		$parser->setCondition('showIcon', $detailSettings->isShowIcons());
		$parser->setCondition('showAvailableSpots', $detailSettings->isShowAvailability());
		$parser->setCondition('showLevel', $detailSettings->isShowLevelCourse());
		$parser->setCondition('showPrice', $detailSettings->isShowPrice());
		$parser->setCondition('showDayPartsDetail', $detailSettings->isShowDayPartCount());
		$parser->setCondition('showCourseElearning', $detailSettings->isShowELearningIcon() && $course->isHasELearning());
		$parser->setCondition('showGaranteedStart', $detailSettings->isShowStartGuaranteeLabel() && $course->isStartGuaranteed());
		$parser->setCondition('showMoneyBack', $detailSettings->isShowMoneyBackLabel() && $course->isMoneyBackGuaranteed());
		$parser->setCondition('showSoobDetail', $detailSettings->isShowSoobLabel() && $course->isHasSoob());
		$parser->setCondition('showCode95', $detailSettings->isShowCode95Label() && $course->isHasCode95());
		$parser->setCondition('showLabels', $detailSettings->isShowLabels() && !empty($courseLabels));
		$parser->setCondition('showDescription', $detailSettings->isShowDescription());
		$parser->setCondition('showCostRemark', $detailSettings->isShowFinancialInfo());
		$parser->setCondition('showDayPartList', $detailSettings->isShowDayPartList());
		$parser->setCondition('showImgInDetail', false);

		$parser->injectAttribute(
			DayPartList::INCLUDE_E_LEARNING_DAY_PARTS_ATTRIBUTE,
			$detailSettings->isIncludeElearningDayParts() ? '1' : null
		);
		$parser->injectAttribute(
			$this->getRecursiveVersionOfAttribute(DayPartItem::SHOW_DESCRIPTION_ATTRIBUTE),
			$detailSettings->isShowDescriptionDayPart() ? '1' : null
		);
		$parser->injectAttribute(
			$this->getRecursiveVersionOfAttribute(DayPartItem::SHOW_ICONS_ATTRIBUTE),
			$detailSettings->isShowIcons() ? '1' : null
		);
		$parser->injectAttribute(
			$this->getRecursiveVersionOfAttribute(DayPartItem::SHOW_LOCATION_ATTRIBUTE),
			$detailSettings->isShowLocationDayPart() ? '1' : null
		);
		$parser->injectAttribute(
			$this->getRecursiveVersionOfAttribute(DayPartItem::SHOW_E_LEARNING_ICON_ATTRIBUTE),
			$detailSettings->isShowELearningDayPart() ? '1' : null
		);
		$parser->injectAttribute(
			$this->getRecursiveVersionOfAttribute(DayPartItem::SHOW_LABELS_ATTRIBUTE),
			$detailSettings->isShowLabelsDayPart() ? '1' : null
		);
	}

	private function initializeExceptionData( Exception $e, HtmlParser $parser): void {
		if ($e instanceof CourseNotFoundException){
			$parser->setData('error-title', $this->localizationController->translate('Kon deze cursus niet vinden'));
		}
		if ($e instanceof InvalidResponseException){
			$parser->setData('error-title', $this->localizationController->translate('Iets is mis gegaan'));
		}

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