<?php

namespace SugarCalendarBookings\Support\ElementorWidgets;

use Exception;
use SugarCalendarBookings\Support\Bootable;

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

/**
 * Elementor Widget Registry.
 *
 * Handles registration and initialization of Elementor widgets.
 *
 * @since 1.0.0
 */
class ElementorWidgetRegistry implements Bootable {

	/**
	 * Available widget classes.
	 *
	 * @since 1.0.0
	 *
	 * @var array<class-string<AbstractElementorWidget>>
	 */
	private $widget_classes = [];

	/**
	 * Check if Elementor is active and loaded.
	 *
	 * @since 1.0.0
	 *
	 * @return bool
	 */
	public function allow_load(): bool {

		return defined( 'ELEMENTOR_VERSION' ) && did_action( 'elementor/loaded' );
	}

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

		add_action( 'elementor/widgets/register', [ $this, 'init_widgets' ] );
		add_action( 'elementor/editor/before_enqueue_scripts', [ $this, 'enqueue_editor_assets' ] );
		add_action( 'wp_enqueue_scripts', [ $this, 'register_widget_scripts' ] );
		add_action( 'elementor/preview/enqueue_scripts', [ $this, 'enqueue_preview_scripts' ] );
	}

	/**
	 * Register widgets.
	 *
	 * @since 1.0.0
	 *
	 * @param array<class-string<AbstractElementorWidget>> $widget_classes List of widget classes.
	 */
	public function register_widgets( $widget_classes ): void {

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

	/**
	 * Initialize all widgets.
	 *
	 * @since 1.0.0
	 *
	 * @param Elementor\Widgets_Manager $widgets_manager Elementor widgets manager.
	 */
	public function init_widgets( $widgets_manager ): void {

		foreach ( $this->get_widget_instances() as $widget ) {
			$widgets_manager->register( $widget );
		}
	}

	/**
	 * Get all widget instances.
	 *
	 * @since 1.0.0
	 *
	 * @return AbstractElementorWidget[]
	 */
	private function get_widget_instances(): array {

		$widgets = [];

		foreach ( $this->widget_classes as $widget_class ) {
			if ( ! is_subclass_of( $widget_class, AbstractElementorWidget::class ) ) {
				continue;
			}

			try {
				$widget = new $widget_class();

				if ( $widget instanceof AbstractElementorWidget && $widget->allow_load() ) {
					$widgets[] = $widget;
				}
			} catch ( Exception $e ) {
				// Silently skip widgets that can't be loaded.
				continue;
			}
		}

		return $widgets;
	}

	/**
	 * Enqueue editor assets for custom widgets.
	 *
	 * @since 1.0.0
	 */
	public function enqueue_editor_assets(): void {

		wp_enqueue_style(
			'scbookings-elementor-editor',
			SCBOOKINGS_PLUGIN_URL . 'assets/dist/styles/admin/elementor/editor.css',
			[],
			SCBOOKINGS_PLUGIN_VERSION
		);
	}

	/**
	 * Register widget scripts according to Elementor standards.
	 *
	 * @since 1.0.0
	 *
	 * @link https://developers.elementor.com/docs/scripts-styles/widget-scripts/
	 */
	public function register_widget_scripts(): void {

		foreach ( $this->get_widget_instances() as $widget ) {
			$widget->register_widget_assets();
		}
	}

	/**
	 * Enqueue preview scripts according to Elementor standards.
	 *
	 * @since 1.0.0
	 *
	 * @link https://developers.elementor.com/docs/scripts-styles/preview-scripts/
	 */
	public function enqueue_preview_scripts(): void {

		foreach ( $this->get_widget_instances() as $widget ) {
			$widget->enqueue_preview_assets();
		}
	}
}
