<?php

namespace Planaday\Html\Tags\Form\Booking\PersonInput;

use Planaday\Api\ApiException\InvalidResponseException;
use Planaday\Config\Booking\Form\FormSettings;
use Planaday\Config\Course\General\GeneralSettings;
use Planaday\Entities\Booking\PostRequest\BookingFormFieldEnum;
use Planaday\Entities\Booking\PostRequest\BookingStudentFieldEnum;
use Planaday\Entities\Course\CourseController;
use Planaday\Entities\Course\DTO\Course;
use Planaday\Entities\Course\Exception\CourseNotFoundException;
use Planaday\Entities\PostEntities;
use Planaday\Html\HtmlParser;
use Planaday\Html\Tags\Form\DataInputFieldTag;
use Planaday\Html\Tags\Form\SelectableDataInputFieldTag;
use Planaday\Platform\PlatformAbstraction\DataHandler;
use Planaday\Platform\PlatformAbstraction\UrlHandler;
use Planaday\Utility\DependencyInjection\Container;
use Planaday\Utility\DependencyInjection\InjectionImpossibleException;
use Planaday\Utility\GeneralTermEnum;

class PersonInput extends DataInputFieldTag {
	const TAG = 'booking-form-student-input';
	const DEFAULT_TEMPLATE = 'personInput';
	const JS_INDEX_MARKER = 'pad-js-index';
	const COURSE_ID_ATTRIBUTE = self::ATTRIBUTE_PREFIX . 'course-id';

	protected string $fieldName = BookingFormFieldEnum::STUDENTS;

	protected CourseController $courseController;
	protected DataHandler $dataHandler;
	protected UrlHandler $urlHandler;
	protected FormSettings $formSettings;
	protected GeneralSettings $courseGeneralSettings;

	/**
	 * @param Container $registry
	 *
	 * @throws InjectionImpossibleException
	 */
	public function __construct(Container $registry) {
		$this->courseController      = $registry->getInstance(CourseController::class);
		$this->courseGeneralSettings = $registry->getInstance(GeneralSettings::class);
		$this->formSettings           = $registry->getInstance(FormSettings::class);
		$this->dataHandler = $registry->getInstance(DataHandler::class);
		$this->urlHandler = $registry->getInstance(UrlHandler::class);
		parent::__construct(__DIR__, self::DEFAULT_TEMPLATE, $registry);
	}

	public function buildTag(): string {
		$parser = $this->getNewParser();
		$dataHandler = $this->dataHandler;
		$courseId = $this->attributes[self::COURSE_ID_ATTRIBUTE] ?? null;
		$this->attributes[self::ID_OVERRIDE_ATTRIBUTE] = $parser->getParserUniqueId();

		if ($courseId === null && $dataHandler->isPostDataSet())
			$courseId = $dataHandler->getPostField( GeneralTermEnum::COURSE_ID );
		if ($courseId === null)
			$courseId = $this->urlHandler->getUrlQueryField($this->pluginData->getShortPrefix() . GeneralTermEnum::COURSE_ID_URL_QUERY);
		if ($courseId === null){
			$this->logError('No course id found for person input');
			return $parser->parse($this->getErrorTemplate('', 'noCourse'));
		}

		try {
			$course = $this->courseController->getCourse((int)$courseId);
		} catch ( InvalidResponseException ) {
			return $parser->parse($this->getErrorTemplate());
		} catch ( CourseNotFoundException ) {
			return $parser->parse($this->getErrorTemplate('', 'noCourse'));
		}

		$parser->addScript($this->getScriptPath(self::DEFAULT_TEMPLATE));
		$parser->addStylesheet($this->getStylePath());
		$parser->injectAttribute(
			$this->getRecursiveVersionOfAttribute(self::FIELD_NAME_ARRAY_NAME),
			 $this->getNextFieldNameArray(BookingFormFieldEnum::STUDENTS)
		);

		$parser->injectAttribute(
			$this->getRecursiveVersionOfAttribute(SelectableDataInputFieldTag::FIELD_CLASS_ATTRIBUTE),
			BookingStudentFieldEnum::class
		);
		$parser->injectAttribute(
			SelectableDataInputFieldTag::FIELD_CLASS_ATTRIBUTE,
			BookingStudentFieldEnum::class
		);

		$this->setTemplates($parser, $course);

		$parser->setData('jsIndexMarker', self::JS_INDEX_MARKER);
		$parser->setData('maxCount', $course->getUsersData()->getAvailableSpots($this->courseGeneralSettings->isIncludeOptionInCount()));

		$showCompanyDetails = $dataHandler->getPostField(PostEntities::BOOKING_FORM)[BookingFormFieldEnum::AS_COMPANY] ??
		                      $this->formSettings->getCompanySettings()->isAsCompanyDefault();
		$parser->setData('displayCompanyDetails', $showCompanyDetails ? 'block' : 'none');

		$canAddStudents =
			count($course->getAttributes()) == 0 &&
			!$course->isHasStap();

		$parser->setCondition('canAddStudents', $canAddStudents && empty($this->attributes['company_id_isset']));
		$parser->setCondition('canNotAddStudents', !$canAddStudents);
		return $parser->parse($this->getTemplate());
	}

	protected function setTemplateConditions(HtmlParser $parser, Course $course): void {
		$studentSettings = $this->formSettings->getStudentSettings();

		$parser->setCondition('showDeleteButton', false);
		$parser->setCondition('showGender', $studentSettings->isAskGender());
		$parser->setCondition('showInitials', $studentSettings->isAskInitials());
		$parser->setCondition('showNickName', $studentSettings->isAskNickName());
		$parser->setCondition('showMaidenName', $studentSettings->isAskMaidenName());
		$parser->setCondition('showAddressBlock', $studentSettings->isAskAddress() || ($course->isHasStap()));
		$parser->setCondition('showHouseNumberExtension', $this->formSettings->getAddressSettings()->isAskForNumberExtension() || ($course->isHasStap()));
		$parser->setCondition('showPhoneNumber', $studentSettings->isAskPhoneNumber());
		$parser->setCondition('phoneNumberMandatory', $studentSettings->isPhoneNumberRequired());
		$parser->setCondition('showDateOfBirth', $studentSettings->isAskDateOfBirth() || ($course->isHasStap()));
		$parser->setCondition('dateOfBirthMandatory', $studentSettings->isDateOfBirthRequired() || ($course->isHasStap()));
		$parser->setCondition('showPlaceOfBirth', $studentSettings->isAskPlaceOfBirth());
		$parser->setCondition('placeOfBirthMandatory', $studentSettings->isPlaceOfBirthRequired());
		$parser->setCondition('showCompanyPosition', $studentSettings->isAskCompanyPosition());
		$parser->setCondition('companyPositionMandatory', $studentSettings->isCompanyPositionRequired());
		$parser->setCondition('showCostCenterCode', $studentSettings->isAskCostCenterCode());
		$parser->setCondition('costCenterCodeMandatory', $studentSettings->isCostCenterCodeRequired());
		$parser->setCondition('showEmployeeNumber', $studentSettings->isAskEmployeeNumber());
		$parser->setCondition('showInternalReference', $studentSettings->isAskInternalReference());
		$parser->setCondition('showStudentRemark', $studentSettings->isAskRemark());
		$parser->setCondition('showContactPerson', $studentSettings->isAskIfContact());
		$parser->setCondition('hasStap', $course->isHasStap());
		$parser->setCondition('onlyStap', $course->isStapOnly());
		$parser->setCondition('notOnlyStap', !$course->isStapOnly());
		$parser->setCondition('hasCode95', $course->isHasCode95() && $studentSettings->isAskCode95());
		$parser->setCondition('hasSoob', $course->isHasSoob() && $studentSettings->isAskSoob());
	}

	protected function setTemplateData(HtmlParser $parser): void {
		$showCompanyDetails = $this->dataHandler->getPostField(BookingFormFieldEnum::AS_COMPANY) ?? !$this->formSettings->getCompanySettings()->isAsCompanyDefault();
		$parser->setData('displayCompanyDetails', $showCompanyDetails ? 'block' : 'none');

		$parser->setData('costCenterCodeText', $this->formSettings->getStudentSettings()->getCostCenterCodeText());
		$parser->setData('code95text', $this->formSettings->getStudentSettings()->getCode95Text());
		$parser->setData('soobText', $this->formSettings->getStudentSettings()->getSoobText());
	}

	protected function setTemplates(HtmlParser $mainParser, Course $course): void {
		$parser = $this->getNewParser();
		$parser->injectAttribute(
			$this->getRecursiveVersionOfAttribute(SelectableDataInputFieldTag::FIELD_CLASS_ATTRIBUTE),
			BookingStudentFieldEnum::class
		);
		$parser->injectAttribute(
			SelectableDataInputFieldTag::FIELD_CLASS_ATTRIBUTE,
			BookingStudentFieldEnum::class
		);
		$currentArray = $this->getCurrentFieldValue();
		$this->setTemplateConditions($parser, $course);
		$this->setTemplateData($parser);

		$showCompanyDetails = $this->dataHandler->getPostField(PostEntities::BOOKING_FORM)[BookingFormFieldEnum::AS_COMPANY] ?? $this->formSettings->getCompanySettings()->isAsCompanyDefault();
		$parser->setData('displayCompanyDetails', $showCompanyDetails ? 'block' : 'none');

		$buildCount = (is_array($currentArray) && count($currentArray) > 1) ? count($currentArray) - 1 : 1;
		$inputField = '';

		for ( $i = 0; $i < $buildCount; $i ++ ) {
			$parser->setData('jsIndexMarker', $i);
			$parser->injectAttribute(
				$this->getRecursiveVersionOfAttribute(self::FIELD_NAME_ARRAY_INDEX),
				$i
			);
			$parser->injectAttribute(
				$this->getRecursiveVersionOfAttribute(self::ID_OVERRIDE_ATTRIBUTE),
				((string)$i) . '-' . $parser->getParserUniqueId()
			);
			$inputField .= $parser->parse($this->getTemplate('Template'));
			$parser->setCondition('showDeleteButton', true);
		}

		$parser->injectAttribute(
			$this->getRecursiveVersionOfAttribute(self::FIELD_NAME_ARRAY_INDEX),
			self::JS_INDEX_MARKER
		);
		$parser->injectAttribute(
			$this->getRecursiveVersionOfAttribute(self::ID_OVERRIDE_ATTRIBUTE),
			self::JS_INDEX_MARKER . '-' . $parser->getParserUniqueId()
		);
		$parser->setData('jsIndexMarker', self::JS_INDEX_MARKER);
		$template = $parser->parse($this->getTemplate('Template'));

		$mainParser->setData('startCount', $buildCount);
		$mainParser->setUnsafeData('templateOutput', $template);
		$mainParser->setUnsafeData('filledInTemplatesOutput', $inputField);
	}
}