<?php

namespace SugarCalendarBookings\Support\Shortcodes;

use SugarCalendarBookings\Support\Bootable;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Shortcode Registry.
 *
 * Handles registration and initialization of shortcodes.
 *
 * @since 1.0.0
 */
class ShortcodeRegistry implements Bootable {

	/**
	 * Available shortcode classes.
	 *
	 * @since 1.0.0
	 *
	 * @var array<class-string<AbstractShortcode>>
	 */
	private $shortcode_classes = [];

	/**
	 * Register hooks.
	 *
	 * @since 1.0.0
	 */
	public function hooks(): void {

		add_action( 'init', [ $this, 'init_shortcodes' ] );
	}

	/**
	 * Register shortcodes.
	 *
	 * @since 1.0.0
	 *
	 * @param array<class-string<AbstractShortcode>> $shortcode_classes List of shortcode classes.
	 */
	public function register_shortcodes( $shortcode_classes ): void {

		$this->shortcode_classes = array_merge( $this->shortcode_classes, $shortcode_classes );
	}

	/**
	 * Initialize all shortcodes.
	 *
	 * @since 1.0.0
	 */
	public function init_shortcodes(): void {

		foreach ( $this->get_shortcode_instances() as $shortcode ) {
			$shortcode->register();
		}
	}

	/**
	 * Get all shortcode instances.
	 *
	 * @since 1.0.0
	 *
	 * @return AbstractShortcode[]
	 */
	private function get_shortcode_instances(): array {

		$shortcodes = [];

		foreach ( $this->shortcode_classes as $shortcode_class ) {
			if ( ! is_subclass_of( $shortcode_class, AbstractShortcode::class ) ) {
				continue;
			}

			try {
				$shortcode = new $shortcode_class();

				if ( $shortcode instanceof AbstractShortcode ) {
					$shortcodes[] = $shortcode;
				}
			} catch ( \Exception $e ) {
				// Silently skip shortcodes that can't be loaded.
				continue;
			}
		}

		return $shortcodes;
	}
}
