<?php
/**
 * @package Hafenstudios\Leadlotse
 */

namespace Hafenstudios\Leadlotse\Fields;

use Hafenstudios\Core\Events\EventBus;
use Hafenstudios\Leadlotse\Fields\Types\CheckboxField;
use Hafenstudios\Leadlotse\Fields\Types\ConsentField;
use Hafenstudios\Leadlotse\Fields\Types\DateField;
use Hafenstudios\Leadlotse\Fields\Types\EmailField;
use Hafenstudios\Leadlotse\Fields\Types\HiddenField;
use Hafenstudios\Leadlotse\Fields\Types\HoneypotField;
use Hafenstudios\Leadlotse\Fields\Types\NumberField;
use Hafenstudios\Leadlotse\Fields\Types\PhoneField;
use Hafenstudios\Leadlotse\Fields\Types\SelectField;
use Hafenstudios\Leadlotse\Fields\Types\TextareaField;
use Hafenstudios\Leadlotse\Fields\Types\TextField;

defined( 'ABSPATH' ) || exit;

/**
 * Registry der 10 Basisfeldtypen (BAUPLAN 12). Ueber den Flotten-Filter
 * `hafenstudios/leadlotse_field_types` erweiterbar (Pro-Erweiterungspunkt fuer
 * Uploads, Berechnungen usw., ohne Pro-Stubs in 1.0).
 */
final class FieldRegistry {

	/**
	 * @var array<string, FieldType>|null
	 */
	private ?array $types = null;

	/**
	 * Liefert alle registrierten Feldtypen (key => Instanz).
	 *
	 * @return array<string, FieldType>
	 */
	public function all(): array {
		if ( null === $this->types ) {
			$types = array();
			foreach ( $this->defaults() as $type ) {
				$types[ $type->key() ] = $type;
			}

			/**
			 * Erweiterungspunkt fuer zusaetzliche Feldtypen.
			 *
			 * @param array<string, FieldType> $types Registrierte Typen.
			 */
			$types = EventBus::filter( 'leadlotse_field_types', $types );

			$this->types = array_filter(
				$types,
				static function ( $type ): bool {
					return $type instanceof FieldType;
				}
			);
		}
		return $this->types;
	}

	/**
	 * Liefert einen Feldtyp.
	 *
	 * @param string $key Typ-Schluessel.
	 * @return FieldType|null
	 */
	public function get( string $key ): ?FieldType {
		$types = $this->all();
		return $types[ $key ] ?? null;
	}

	/**
	 * Existiert der Typ?
	 *
	 * @param string $key Typ-Schluessel.
	 * @return bool
	 */
	public function has( string $key ): bool {
		return null !== $this->get( $key );
	}

	/**
	 * Die Basistypen (10 aus 1.0 plus Zahl seit 1.2, L-R1).
	 *
	 * @return array<int, FieldType>
	 */
	private function defaults(): array {
		return array(
			new TextField(),
			new EmailField(),
			new PhoneField(),
			new NumberField(),
			new TextareaField(),
			new SelectField(),
			new CheckboxField(),
			new DateField(),
			new ConsentField(),
			new HiddenField(),
			new HoneypotField(),
		);
	}
}
