<?php

namespace Planaday\Utility\FormBuilder\InputFields;

use Planaday\Utility\FormBuilder\DataType;
use Planaday\Utility\FormBuilder\InputField;
use Planaday\Utility\FormBuilder\InvalidFormDataException;

/**
 * @template T
 * @implements InputField<T>
 */
class RadioInput implements InputField {
	use BasicInputField{
		validate as traitValidate;
	}

	/**
	 * @param DataType<T> $dataType
	 */
	public function __construct(
		DataType $dataType
	) {
		$this->dataType = $dataType;
	}

	protected array $options = [];
	protected bool $allowCustom = false;
	protected ?InputField $customInput = null;

	public function setOptions(iterable $options): self {
		$this->options = [];

		foreach ($options as $option) {
			if (is_array($option)) {
				$this->options[] = $option;
				continue;
			}

			$this->options[] = [
				'value' => $option,
				'label' => $option
			];
		}
		return $this;
	}

	public function getOptions(): array {
		return $this->options;
	}

	public function setAllowCustom( bool $allowCustom ): self {
		$this->allowCustom = $allowCustom;
		return $this;
	}

	public function setCustomInput( InputField $customInput ): self {
		$this->customInput = $customInput;
		return $this;
	}

	public function validate(): bool|InvalidFormDataException {
		if (!$this->validateConditions()) return true;
		$basicValidate = $this->traitValidate();
		if ($this->allowCustom) {
			return $basicValidate;
		}

		if ($this->value === null) return true;

		$inArray = false;

		foreach ( $this->options as $option ) {
			if ( $option['value'] === $this->value ) {
				$inArray = true;
				break;
			}
		}

		if ( $inArray === false ) {
			if ( $basicValidate === true ) {
				$basicValidate = new InvalidFormDataException();
			}

			$basicValidate->addError( 'RadioInput', 'Input was not a valid option.' );
			return $basicValidate;
		}

		return $basicValidate;
	}

	public function getImplJson(): array {
		return [
			"type" => 'radio',
			"options" => $this->options,
			"allowCustom" => $this->allowCustom,
			"customInput" => $this->customInput
		];
	}
}