<?php

namespace Planaday\Entities\Course\DTO;

use Planaday\Entities\Course\PostRequest\CourseSearchFieldEnum;

class CourseSearch {
	protected $ids;
	protected $codes;
	protected $name;
	protected $description;
	protected $types;
	protected $statuses;
	protected $needsDayPartInfo;
	protected $dayPartAmountMin;
	protected $dayPartAmountMax;
	protected $dayPartName;
	protected $dayPartDescription;
	protected $locations;
	protected $instructors;
	protected $dayPartLabels;
	protected $dateMin;
	protected $dateMax;
	protected $endDateMin;
	protected $endDateMax;
	protected $startTimeMin;
	protected $startTimeMax;
	protected $endTimeMin;
	protected $endTimeMax;
	protected $usersMinMin;
	protected $usersMinMax;
	protected $usersMaxMin;
	protected $usersMaxMax;
	protected $usersScheduledMin;
	protected $usersScheduledMax;
	protected $usersAvailableMin;
	protected $usersAvailableMax;
	protected $usersOptionsMin;
	protected $usersOptionsMax;
	protected $costMin;
	protected $costMax;
	protected $courseCostMin;
	protected $courseCostMax;
	protected $vatMin;
	protected $vatMax;
	protected $vatCodes;
	protected $costRemark;
	protected $templateIds;
	protected $levels;
	protected $levelDescription;
	protected $isStartGuaranteed;
	protected $isMoneyBackGuaranteed;
	protected $hasELearning;
	protected $hasCode95;
	protected $hasSoob;
	protected $hasStap;
	protected $isStapOnly;
	protected $labels;
	protected $languages;
	protected $companies;
	protected $cities;

	/**
	 * @param array<mixed> $searchArgs
	 */
	public function __construct(array $searchArgs) {
		$this->ids = $this->getArrayFromArrayOrString($searchArgs[CourseSearchFieldEnum::IDS] ?? null);
		$this->codes = $this->getArrayFromArrayOrString($searchArgs[CourseSearchFieldEnum::CODES] ?? null);
		$this->name = $this->getStringFromString($searchArgs[CourseSearchFieldEnum::NAME] ?? null);
		$this->description = $this->getStringFromString($searchArgs[CourseSearchFieldEnum::DESCRIPTION] ?? null);
		$this->types = $this->getArrayFromArrayOrString($searchArgs[CourseSearchFieldEnum::TYPES] ?? null);
		$this->statuses = $this->getArrayFromArrayOrString($searchArgs[CourseSearchFieldEnum::STATUSES] ?? null);
		$this->dayPartAmountMin = $searchArgs[CourseSearchFieldEnum::DAY_PART_AMOUNT_MIN] ?? null;
		$this->dayPartAmountMax = $searchArgs[CourseSearchFieldEnum::DAY_PART_AMOUNT_MAX] ?? null;
		$this->dayPartName = $this->getStringFromString($searchArgs[CourseSearchFieldEnum::DAY_PART_NAME] ?? null);
		$this->dayPartDescription = $this->getStringFromString($searchArgs[CourseSearchFieldEnum::DAY_PART_DESCRIPTION] ?? null);
		$this->locations = $this->getArrayFromArrayOrString($searchArgs[CourseSearchFieldEnum::LOCATIONS] ?? null);
		$this->instructors = $this->getArrayFromArrayOrString($searchArgs[CourseSearchFieldEnum::INSTRUCTORS] ?? null);
		$this->dayPartLabels = $this->getArrayFromArrayOrString($searchArgs[CourseSearchFieldEnum::DAY_PART_LABELS] ?? null);
		$this->dateMin = $searchArgs[CourseSearchFieldEnum::DATE_MIN] ?? null;
		$this->dateMax = $searchArgs[CourseSearchFieldEnum::DATE_MAX] ?? null;
		$this->endDateMin = $searchArgs[CourseSearchFieldEnum::END_DATE_MIN] ?? null;
		$this->endDateMax = $searchArgs[CourseSearchFieldEnum::END_DATE_MAX] ?? null;
		$this->startTimeMin = $searchArgs[CourseSearchFieldEnum::START_TIME_MIN] ?? null;
		$this->startTimeMax = $searchArgs[CourseSearchFieldEnum::START_TIME_MAX] ?? null;
		$this->endTimeMin = $searchArgs[CourseSearchFieldEnum::END_TIME_MIN] ?? null;
		$this->endTimeMax = $searchArgs[CourseSearchFieldEnum::END_TIME_MAX] ?? null;

		$this->usersMinMin = $searchArgs[CourseSearchFieldEnum::USERS_MIN_MIN] ?? null;
		$this->usersMinMax = $searchArgs[CourseSearchFieldEnum::USERS_MIN_MAX] ?? null;
		$this->usersMaxMin = $searchArgs[CourseSearchFieldEnum::USERS_MAX_MIN] ?? null;
		$this->usersMaxMax = $searchArgs[CourseSearchFieldEnum::USERS_MAX_MAX] ?? null;
		$this->usersScheduledMin = $searchArgs[CourseSearchFieldEnum::USERS_SCHEDULED_MIN] ?? null;
		$this->usersScheduledMax = $searchArgs[CourseSearchFieldEnum::USERS_SCHEDULED_MAX] ?? null;
		$this->usersAvailableMin = $searchArgs[CourseSearchFieldEnum::USERS_AVAILABLE_MIN] ?? null;
		$this->usersAvailableMax = $searchArgs[CourseSearchFieldEnum::USERS_AVAILABLE_MAX] ?? null;
		$this->usersOptionsMin = $searchArgs[CourseSearchFieldEnum::USERS_OPTIONS_MIN] ?? null;
		$this->usersOptionsMax = $searchArgs[CourseSearchFieldEnum::USERS_OPTIONS_MAX] ?? null;
		$this->costMin = $searchArgs[CourseSearchFieldEnum::COST_MIN] ?? null;
		$this->costMax = $searchArgs[CourseSearchFieldEnum::COST_MAX] ?? null;
		$this->courseCostMin = $searchArgs[CourseSearchFieldEnum::COURSE_COST_MIN] ?? null;
		$this->courseCostMax = $searchArgs[CourseSearchFieldEnum::COURSE_COST_MAX] ?? null;
		$this->vatMin = $searchArgs[CourseSearchFieldEnum::VAT_MIN] ?? null;
		$this->vatMax = $searchArgs[CourseSearchFieldEnum::VAT_MAX] ?? null;
		$this->vatCodes = $this->getArrayFromArrayOrString($searchArgs[CourseSearchFieldEnum::VAT_CODES] ?? null);
		$this->costRemark = $this->getStringFromString($searchArgs[CourseSearchFieldEnum::COST_REMARK] ?? null);
		$this->templateIds = $this->getArrayFromArrayOrString($searchArgs[CourseSearchFieldEnum::TEMPLATE_IDS] ?? null);
		$this->levels = $this->getArrayFromArrayOrString($searchArgs[CourseSearchFieldEnum::LEVELS] ?? null);
		$this->levelDescription = $this->getStringFromString($searchArgs[CourseSearchFieldEnum::LEVEL_DESCRIPTION] ?? null);
		$this->isStartGuaranteed = $this->getBoolFromString($searchArgs[CourseSearchFieldEnum::IS_START_GUARANTEED] ?? null);
		$this->isMoneyBackGuaranteed = $this->getBoolFromString($searchArgs[CourseSearchFieldEnum::IS_MONEY_BACK_GUARANTEED] ?? null);
		$this->hasELearning = $this->getBoolFromString($searchArgs[CourseSearchFieldEnum::HAS_E_LEARNING] ?? null);
		$this->hasCode95 = $this->getBoolFromString($searchArgs[CourseSearchFieldEnum::HAS_CODE95] ?? null);
		$this->hasSoob = $this->getBoolFromString($searchArgs[CourseSearchFieldEnum::HAS_SOOB] ?? null);
		$this->hasStap = $this->getBoolFromString($searchArgs[CourseSearchFieldEnum::HAS_STAP] ?? null);
		$this->isStapOnly = $this->getBoolFromString($searchArgs[CourseSearchFieldEnum::IS_STAP_ONLY] ?? null);
		$this->labels = $this->getArrayFromArrayOrString($searchArgs[CourseSearchFieldEnum::LABELS] ?? null);
		$this->languages = $this->getArrayFromArrayOrString($searchArgs[CourseSearchFieldEnum::LANGUAGES] ?? null);
		$this->companies = $this->getArrayFromArrayOrString($searchArgs[CourseSearchFieldEnum::COMPANIES] ?? null);
		$this->cities = $this->getArrayFromArrayOrString($searchArgs[CourseSearchFieldEnum::CITIES] ?? null);

		$this->needsDayPartInfo = isset( $this->dayPartName ) ||
		                          isset( $this->dayPartDescription) ||
		                          isset( $this->locations) ||
		                          isset( $this->instructors) ||
		                          isset( $this->dayPartLabels) ||
		                          isset( $this->dateMin) ||
		                          isset( $this->dateMax) ||
		                          isset( $this->endDateMin) ||
		                          isset( $this->endDateMax) ||
		                          isset( $this->startTimeMin) ||
		                          isset( $this->startTimeMax) ||
		                          isset( $this->endTimeMin) ||
		                          isset( $this->endTimeMax) ||
		                          isset( $this->cities);
	}


	/**
	 * @param int[] $ids
	 *
	 * @return void
	 */
	public function setIds(array $ids ): void {
		$this->ids = $ids;
	}

	/**
	 * @param string[] $codes
	 *
	 * @return void
	 */
	public function setCodes(array $codes ): void {
		$this->codes = $codes;
	}

	public function setName(string $name ): void {
		$this->name = $name;
	}

	public function setDescription(string $description ): void {
		$this->description = $description;
	}

	/**
	 * @param string[] $types
	 *
	 * @return void
	 */
	public function setTypes(array $types ): void {
		$this->types = $types;
	}

	/**
	 * @param string[] $statuses
	 *
	 * @return void
	 */
	public function setStatuses(array $statuses ): void {
		$this->statuses = $statuses;
	}

	public function setDayPartAmountMin(int $dayPartAmountMin ): void {
		$this->needsDayPartInfo = true;
		$this->dayPartAmountMin = $dayPartAmountMin;
	}

	public function setDayPartAmountMax(int $dayPartAmountMax ): void {
		$this->needsDayPartInfo = true;
		$this->dayPartAmountMax = $dayPartAmountMax;
	}

	public function setDayPartName(string $dayPartName ): void {
		$this->needsDayPartInfo = true;
		$this->dayPartName      = $dayPartName;
	}

	public function setDayPartDescription(string $dayPartDescription ): void {
		$this->needsDayPartInfo   = true;
		$this->dayPartDescription = $dayPartDescription;
	}

	/**
	 * @param int[] $locations
	 *
	 * @return void
	 */
	public function setLocations(array $locations ): void {
		$this->needsDayPartInfo = true;
		$this->locations = $locations;
	}

	/**
	 * @param int[] $instructors
	 *
	 * @return void
	 */
	public function setInstructors(array $instructors ): void {
		$this->needsDayPartInfo = true;
		$this->instructors = $instructors;
	}

	/**
	 * @param string[] $dayPartLabels
	 *
	 * @return void
	 */
	public function setDayPartLabels(array $dayPartLabels ): void {
		$this->needsDayPartInfo = true;
		$this->dayPartLabels = $dayPartLabels;
	}

	public function setDateMin(string $dateMin ): void {
		$this->needsDayPartInfo = true;
		$this->dateMin = $dateMin;
	}

	public function setDateMax(string $dateMax ): void {
		$this->needsDayPartInfo = true;
		$this->dateMax = $dateMax;
	}

	public function setEndDateMin(string $endDateMin ): void {
		$this->needsDayPartInfo = true;
		$this->endDateMin = $endDateMin;
	}

	public function setEndDateMax(string $endDateMax ): void {
		$this->needsDayPartInfo = true;
		$this->endDateMax = $endDateMax;
	}

	public function setStartTimeMin(string $startTimeMin ): void {
		$this->needsDayPartInfo = true;
		$this->startTimeMin = $startTimeMin;
	}

	public function setStartTimeMax(string $startTimeMax ): void {
		$this->needsDayPartInfo = true;
		$this->startTimeMax = $startTimeMax;
	}

	public function setEndTimeMin(string $endTimeMin ): void {
		$this->needsDayPartInfo = true;
		$this->endTimeMin = $endTimeMin;
	}

	public function setEndTimeMax(string $endTimeMax ): void {
		$this->needsDayPartInfo = true;
		$this->endTimeMax = $endTimeMax;
	}

	public function setUsersMinMin(int $usersMinMin ): void {
		$this->usersMinMin = $usersMinMin;
	}

	public function setUsersMinMax(int $usersMinMax ): void {
		$this->usersMinMax = $usersMinMax;
	}

	public function setUsersMaxMin(int $usersMaxMin ): void {
		$this->usersMaxMin = $usersMaxMin;
	}

	public function setUsersMaxMax(int $usersMaxMax ): void {
		$this->usersMaxMax = $usersMaxMax;
	}

	public function setUsersScheduledMin(int $usersScheduledMin ): void {
		$this->usersScheduledMin = $usersScheduledMin;
	}

	public function setUsersScheduledMax(int $usersScheduledMax ): void {
		$this->usersScheduledMax = $usersScheduledMax;
	}

	public function setUsersAvailableMin(int $usersAvailableMin ): void {
		$this->usersAvailableMin = $usersAvailableMin;
	}

	public function setUsersAvailableMax(int $usersAvailableMax ): void {
		$this->usersAvailableMax = $usersAvailableMax;
	}

	public function setUsersOptionsMin(int $usersOptionsMin ): void {
		$this->usersOptionsMin = $usersOptionsMin;
	}

	public function setUsersOptionsMax(int $usersOptionsMax ): void {
		$this->usersOptionsMax = $usersOptionsMax;
	}

	public function setCostMin(float $costMin ): void {
		$this->costMin = $costMin;
	}

	public function setCostMax(float $costMax ): void {
		$this->costMax = $costMax;
	}

	public function setCourseCostMin(float $courseCostMin ): void {
		$this->courseCostMin = $courseCostMin;
	}

	public function setCourseCostMax(float $courseCostMax ): void {
		$this->courseCostMax = $courseCostMax;
	}

	public function setVatMin(float $vatMin ): void {
		$this->vatMin = $vatMin;
	}

	public function setVatMax(float $vatMax ): void {
		$this->vatMax = $vatMax;
	}

	/**
	 * @param int[] $vatCodes
	 *
	 * @return void
	 */
	public function setVatCodes(array $vatCodes ): void {
		$this->vatCodes = $vatCodes;
	}

	public function setCostRemark(string $costRemark ): void {
		$this->costRemark = $costRemark;
	}

	/**
	 * @param int[] $templateIds
	 *
	 * @return void
	 */
	public function setTemplateIds(array $templateIds ): void {
		$this->templateIds = $templateIds;
	}

	/**
	 * @param string[] $levels
	 *
	 * @return void
	 */
	public function setLevels(array $levels ): void {
		$this->levels = $levels;
	}

	public function setLevelDescription(string $levelDescription ): void {
		$this->levelDescription = $levelDescription;
	}

	public function setIsStartGuaranteed(bool $isStartGuaranteed ): void {
		$this->isStartGuaranteed = $isStartGuaranteed;
	}

	public function setIsMoneyBackGuaranteed(bool $isMoneyBackGuaranteed ): void {
		$this->isMoneyBackGuaranteed = $isMoneyBackGuaranteed;
	}

	public function setHasELearning(bool $hasELearning ): void {
		$this->hasELearning = $hasELearning;
	}

	public function setHasCode95(bool $hasCode95 ): void {
		$this->hasCode95 = $hasCode95;
	}

	public function setHasSoob(bool $hasSoob ): void {
		$this->hasSoob = $hasSoob;
	}

	public function setHasStap(bool $hasStap ): void {
		$this->hasStap = $hasStap;
	}

	public function setIsStapOnly(bool $isStapOnly ): void {
		$this->isStapOnly = $isStapOnly;
	}

	/**
	 * @param string[] $labels
	 *
	 * @return void
	 */
	public function setLabels(array $labels ): void {
		$this->labels = $labels;
	}

	/**
	 * @param string[] $languages
	 *
	 * @return void
	 */
	public function setLanguages(array $languages ): void {
		$this->languages = $languages;
	}

	/**
	 * @param int[] $companies
	 */
	public function setCompanies(array $companies ): void {
		$this->companies = $companies;
	}

	/**
	 * @return int[]|null
	 */
	public function getIds():?array{
		return $this->ids;
	}

	/**
	 * @return string[]|null
	 */
	public function getCodes():?array{
		return $this->codes;
	}

	public function getName():?string {
		return $this->name;
	}

	public function getDescription():?string {
		return $this->description;
	}

	/**
	 * @return string[]|null
	 */
	public function getTypes():?array{
		return $this->types;
	}

	/**
	 * @return string[]|null
	 */
	public function getStatuses():?array{
		return $this->statuses;
	}

	public function getNeedsDayPartInfo():bool {
		return $this->needsDayPartInfo;
	}

	public function getDayPartAmountMin():?int {
		return $this->dayPartAmountMin;
	}

	public function getDayPartAmountMax():?int {
		return $this->dayPartAmountMax;
	}

	public function getDayPartName():?string {
		return $this->dayPartName;
	}

	public function getDayPartDescription():?string {
		return $this->dayPartDescription;
	}

	/**
	 * @return int[]|null
	 */
	public function getLocations() :?array{
		return $this->locations;
	}

	/**
	 * @return string[]|null
	 */
	public function getCities():?array {
		return $this->cities;
	}

	/**
	 * @return int[]|null
	 */
	public function getInstructors() :?array{
		return $this->instructors;
	}

	/**
	 * @return string[]|null
	 */
	public function getDayPartLabels() :?array{
		return $this->dayPartLabels;
	}

	public function getDateMin():?string {
		return $this->dateMin;
	}

	public function getDateMax():?string {
		return $this->dateMax;
	}

	public function getEndDateMin():?string {
		return $this->endDateMin;
	}

	public function getEndDateMax():?string {
		return $this->endDateMax;
	}

	public function getStartTimeMin():?string {
		return $this->startTimeMin;
	}

	public function getStartTimeMax():?string {
		return $this->startTimeMax;
	}

	public function getEndTimeMin():?string {
		return $this->endTimeMin;
	}

	public function getEndTimeMax():?string {
		return $this->endTimeMax;
	}

	public function getUsersMinMin():?int {
		return $this->usersMinMin;
	}

	public function getUsersMinMax():?int {
		return $this->usersMinMax;
	}

	public function getUsersMaxMin():?int {
		return $this->usersMaxMin;
	}

	public function getUsersMaxMax():?int {
		return $this->usersMaxMax;
	}

	public function getUsersScheduledMin():?int {
		return $this->usersScheduledMin;
	}

	public function getUsersScheduledMax():?int {
		return $this->usersScheduledMax;
	}

	public function getUsersAvailableMin():?int {
		return $this->usersAvailableMin;
	}

	public function getUsersAvailableMax():?int {
		return $this->usersAvailableMax;
	}

	public function getUsersOptionsMin():?int {
		return $this->usersOptionsMin;
	}

	public function getUsersOptionsMax():?int {
		return $this->usersOptionsMax;
	}

	public function getCostMin():?float {
		return $this->costMin;
	}

	public function getCostMax():?float {
		return $this->costMax;
	}

	public function getCourseCostMin():?float {
		return $this->courseCostMin;
	}

	public function getCourseCostMax():?float {
		return $this->courseCostMax;
	}

	public function getVatMin():?float {
		return $this->vatMin;
	}

	public function getVatMax():?float {
		return $this->vatMax;
	}

	/**
	 * @return int[]|null
	 */
	public function getVatCodes() :?array{
		return $this->vatCodes;
	}

	public function getCostRemark():?string {
		return $this->costRemark;
	}

	/**
	 * @return int[]|null
	 */
	public function getTemplateIds() :?array{
		return $this->templateIds;
	}

	/**
	 * @return string[]|null
	 */
	public function getLevels() :?array{
		return $this->levels;
	}

	public function getLevelDescription():?string {
		return $this->levelDescription;
	}

	public function getIsStartGuaranteed():?bool {
		return $this->isStartGuaranteed;
	}

	public function getIsMoneyBackGuaranteed():?bool {
		return $this->isMoneyBackGuaranteed;
	}

	public function getHasELearning():?bool {
		return $this->hasELearning;
	}

	public function getHasCode95():?bool {
		return $this->hasCode95;
	}

	public function getHasSoob():?bool {
		return $this->hasSoob;
	}

	public function getHasStap():?bool {
		return $this->hasStap;
	}

	public function getIsStapOnly():?bool {
		return $this->isStapOnly;
	}

	/**
	 * @return string[]|null
	 */
	public function getLabels() :?array{
		return $this->labels;
	}

	/**
	 * @return string[]|null
	 */
	public function getLanguages() :?array{
		return $this->languages;
	}

	/**
	 * @return int[]|null
	 */
	public function getCompanies():?array {
		return $this->companies;
	}

	/**
	 * @param mixed|string|array<mixed> $input
	 *
	 * @return array<mixed>|null
	 */
	protected function getArrayFromArrayOrString(mixed $input):?array {
		if (!isset($input)){
			return null;
		}

		if(is_string($input)){
			$array = explode(',', $input);
			foreach ($array as $index => $item){
				$array[$index] = trim($item);
			}

		} elseif (is_iterable($input)){
			$array = $input;
		} else {
			$array = [$input] ;
		}

		$output = [];
		foreach ($array as $item){
			if ($item != '' && $item !== null) $output[] = $item;
		}

		return $output;
	}

	/**
	 * @param mixed $input
	 *
	 * @return string|null
	 */
	protected function getStringFromString(mixed $input):?string {
		if (!isset($input) || $input == '' || !is_string($input)){
			return null;
		}

		return $input;
	}

	/**
	 * @param mixed $input
	 *
	 * @return bool|null
	 */
	protected function getBoolFromString( mixed $input):?bool {
		return match ( $input ) {
			'1', 'ja' => true,
			'0', 'nee' => false,
			default => null,
		};
	}
}