<?php
/**
 * Adapter registry.
 *
 * @package RewindBrevoFormBridge
 */

namespace RewindBrevoFormBridge\Adapters;

use RewindBrevoFormBridge\Feeds\Processor;

defined( 'ABSPATH' ) || exit;

/**
 * Detects which form-plugin adapters can run on this site and exposes them.
 * Third parties add adapters via the `rbfb_adapters` filter.
 *
 * @since 0.3.0
 */
class Registry {

	/**
	 * All registered adapters, keyed by slug.
	 *
	 * @var array<string, Adapter>
	 */
	private array $adapters = array();

	/**
	 * Constructor: build the built-in adapters and apply the filter.
	 *
	 * @since 0.3.0
	 * @param Processor $processor Handed to every built-in adapter.
	 */
	public function __construct( Processor $processor ) {
		$builtin = array(
			new Forminator( $processor ),
			new WpForms( $processor ),
			new Formidable( $processor ),
			new ContactForm7( $processor ),
		);

		foreach ( $builtin as $adapter ) {
			$this->adapters[ $adapter->slug() ] = $adapter;
		}

		/**
		 * Register additional form-plugin adapters.
		 *
		 * @since 0.3.0
		 * @param array<string, Adapter> $adapters Adapters keyed by slug.
		 * @param Processor              $processor The feed processor, for
		 *                                          adapters extending AbstractAdapter.
		 */
		$filtered = apply_filters( 'rbfb_adapters', $this->adapters, $processor );

		if ( is_array( $filtered ) ) {
			$this->adapters = array();
			foreach ( $filtered as $adapter ) {
				if ( $adapter instanceof Adapter ) {
					$this->adapters[ $adapter->slug() ] = $adapter;
				}
			}
		}
	}

	/**
	 * Adapters whose form plugin is active right now.
	 *
	 * @since 0.3.0
	 * @return array<string, Adapter>
	 */
	public function available(): array {
		return array_filter(
			$this->adapters,
			function ( Adapter $adapter ) {
				return $adapter->is_available();
			}
		);
	}

	/**
	 * One adapter by slug, available or not.
	 *
	 * @since 0.3.0
	 * @param string $slug Adapter slug.
	 * @return Adapter|null
	 */
	public function get( string $slug ): ?Adapter {
		return isset( $this->adapters[ $slug ] ) ? $this->adapters[ $slug ] : null;
	}

	/**
	 * Attach submission hooks for every available adapter. Called once on
	 * plugins_loaded — on the front end AND admin, because AJAX submissions
	 * arrive through admin-ajax.php.
	 *
	 * @since 0.3.0
	 * @return void
	 */
	public function register_hooks(): void {
		foreach ( $this->available() as $adapter ) {
			$adapter->register_hooks();
		}
	}
}
