<?php

namespace Planaday\Config\OptionGroups\Course;

use Planaday\Config\OptionGroups\Course\Calendar\CalendarOptionsValidator;
use Planaday\Config\OptionGroups\Course\Detail\DetailOptionsValidator;
use Planaday\Config\OptionGroups\Course\General\GeneralOptionsValidator;
use Planaday\Config\OptionGroups\Course\Overview\OverviewOptionsValidator;
use Planaday\Config\OptionGroups\Course\Search\SearchOptionsValidator;
use Planaday\Platform\PlatformAbstraction\LocalizationController;
use Planaday\Utility\DataFilters\InvalidFieldsException;
use Planaday\Utility\DataFilters\TypeValidator;
use Planaday\Utility\Debug\Log\Logging;

class CourseOptionsValidator {
	use Logging;

	/** @var CalendarOptionsValidator  */
	private $calendarOptionsValidator;

	/** @var DetailOptionsValidator  */
	private $detailOptionsValidator;

	/** @var GeneralOptionsValidator */
	private $generalOptionsValidator;

	/** @var OverviewOptionsValidator */
	private $overviewOptionsValidator;

	/** @var SearchOptionsValidator */
	private $searchOptionsValidator;

	/** @var TypeValidator */
	private $typeValidator;

	/** @var LocalizationController */
	private $translator;

	public function __construct(
		TypeValidator $typeValidator,
		LocalizationController $translator,
		CalendarOptionsValidator $calendarOptionsValidator,
		DetailOptionsValidator $detailOptionsValidator,
		GeneralOptionsValidator $generalOptionsValidator,
		OverviewOptionsValidator $overviewOptionsValidator,
		SearchOptionsValidator $searchOptionsValidator
	) {
		$this->calendarOptionsValidator = $calendarOptionsValidator;
		$this->detailOptionsValidator   = $detailOptionsValidator;
		$this->generalOptionsValidator  = $generalOptionsValidator;
		$this->overviewOptionsValidator = $overviewOptionsValidator;
		$this->searchOptionsValidator   = $searchOptionsValidator;
		$this->typeValidator            = $typeValidator;
		$this->translator               = $translator;
	}

	/**
	 * @param array $data
	 * @param array|null $output if valid, clean data is returned here. if not, errors will be returned here
	 *
	 * @return bool true if valid, false if not
	 */
	public function validate( array $data, ?array &$output): bool {
		$errors = [];
		$tr = $this->translator;

		try {
			$data = $this->getSafeData( $data );
		} catch ( InvalidFieldsException $e ) {
			foreach ( $e->getInvalidFields() as $field => $fieldException ) {
				$errors[ $field ] = $tr->translate(
					'Het ' . strtolower($field) . ' veld bij de cursus opties is met ongeldige data ingevuld.'
				);
			}

			$output = $errors;
			return false;
		}

		if (!$this->calendarOptionsValidator->validate($data[CourseOptionsEnum::CALENDAR_SETTINGS] ?? [], $calendarOptions)) {
			$errors[CourseOptionsEnum::CALENDAR_SETTINGS . '-isValid'] = $tr->translate('De kalender instellingen zijn niet correct ingevuld.');
			$errors[CourseOptionsEnum::CALENDAR_SETTINGS] = $calendarOptions;
		} else {
			$data[CourseOptionsEnum::CALENDAR_SETTINGS] = $calendarOptions;
		}

		if (!$this->detailOptionsValidator->validate($data[CourseOptionsEnum::DETAIL_SETTINGS] ?? [], $detailOutput)) {
			$errors[CourseOptionsEnum::DETAIL_SETTINGS . '-isValid'] = $tr->translate('De detail instellingen zijn niet correct ingevuld.');
			$errors[CourseOptionsEnum::DETAIL_SETTINGS] = $detailOutput;
		} else {
			$data[CourseOptionsEnum::DETAIL_SETTINGS] = $detailOutput;
		}

		if (!$this->generalOptionsValidator->validate($data[CourseOptionsEnum::GENERAL_SETTINGS] ?? [], $generalOutput)) {
			$errors[CourseOptionsEnum::GENERAL_SETTINGS . '-isValid'] = $tr->translate('De algemene instellingen zijn niet correct ingevuld.');
			$errors[CourseOptionsEnum::GENERAL_SETTINGS] = $generalOutput;
		} else {
			$data[CourseOptionsEnum::GENERAL_SETTINGS] = $generalOutput;
		}

		if (!$this->overviewOptionsValidator->validate($data[CourseOptionsEnum::OVERVIEW_SETTINGS] ?? [], $overviewOutput)) {
			$errors[CourseOptionsEnum::OVERVIEW_SETTINGS . '-isValid'] = $tr->translate('De overzicht instellingen zijn niet correct ingevuld.');
			$errors[CourseOptionsEnum::OVERVIEW_SETTINGS] = $overviewOutput;
		} else {
			$data[CourseOptionsEnum::OVERVIEW_SETTINGS] = $overviewOutput;
		}

		if (!$this->searchOptionsValidator->validate($data[CourseOptionsEnum::SEARCH_SETTINGS] ?? [], $searchOutput)) {
			$errors[CourseOptionsEnum::SEARCH_SETTINGS . '-isValid'] = $tr->translate('De zoek instellingen zijn niet correct ingevuld.');
			$errors[CourseOptionsEnum::SEARCH_SETTINGS] = $searchOutput;
		} else {
			$data[CourseOptionsEnum::SEARCH_SETTINGS] = $searchOutput;
		}

		if ( count( $errors ) > 0 ) {
			$output = $errors;
			$this->logWarning("data is not valid", $errors);
			return false;
		}

		$output = $data;
		return true;
	}

	/**
	 * @param array $data
	 *
	 * @return array
	 * @throws InvalidFieldsException
	 */
	private function getSafeData(array $data): array {
		$tv = $this->typeValidator;

		$array = [
			CourseOptionsEnum::CALENDAR_SETTINGS,
			CourseOptionsEnum::DETAIL_SETTINGS,
			CourseOptionsEnum::GENERAL_SETTINGS,
			CourseOptionsEnum::OVERVIEW_SETTINGS,
			CourseOptionsEnum::SEARCH_SETTINGS
		];

		return $tv->getSafeData($data, [], $array);
	}

}