<?php

namespace SugarCalendarBookings\Support\Blocks;

use SugarCalendarBookings\Support\Bootable;

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

/**
 * Blocks Service.
 *
 * Handles registration and initialization of Gutenberg blocks.
 *
 * @since 1.0.0
 */
class BlocksRegistry implements Bootable {

	/**
	 * Available block classes.
	 *
	 * @since 1.0.0
	 *
	 * @var array<class-string<AbstractBlock>>
	 */
	private $block_classes = [];

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

		add_action( 'init', [ $this, 'init_blocks' ] );
		add_action( 'enqueue_block_editor_assets', [ $this, 'enqueue_block_editor_assets' ] );
		add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_view_assets' ] );

		// Register block category.
		if ( version_compare( get_bloginfo( 'version' ), '5.8', '>=' ) ) {
			add_filter( 'block_categories_all', [ $this, 'register_block_category' ] );
		} else {
			add_filter( 'block_categories', [ $this, 'register_block_category' ] );
		}
	}

	/**
	 * Register blocks.
	 *
	 * @since 1.0.0
	 *
	 * @param array<class-string<AbstractBlock>> $block_classes List of block classes.
	 */
	public function register_blocks( $block_classes ): void {

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

	/**
	 * Initialize all blocks.
	 *
	 * @since 1.0.0
	 */
	public function init_blocks(): void {

		foreach ( $this->get_block_instances() as $block ) {
			$block->register();
		}
	}

	/**
	 * Enqueue block editor assets.
	 *
	 * @since 1.0.0
	 */
	public function enqueue_block_editor_assets(): void {

		foreach ( $this->get_block_instances() as $block ) {
			$block->enqueue_editor_assets();
		}
	}

	/**
	 * Enqueue view assets.
	 *
	 * @since 1.0.0
	 */
	public function enqueue_view_assets(): void {

		foreach ( $this->get_block_instances() as $block ) {
			$block->enqueue_view_assets();
		}
	}

	/**
	 * Register the Sugar Calendar block category.
	 *
	 * @since 1.0.0
	 *
	 * @param array $categories Block categories.
	 *
	 * @return array
	 */
	public function register_block_category( $categories ) {

		return array_merge(
			[
				[
					'slug'  => 'sugar-calendar',
					'title' => esc_html__( 'Sugar Calendar', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
				],
			],
			$categories
		);
	}

	/**
	 * Get all block instances.
	 *
	 * @since 1.0.0
	 *
	 * @return AbstractBlock[]
	 */
	private function get_block_instances(): array {

		$blocks = [];

		foreach ( $this->block_classes as $block_class ) {
			if ( ! is_subclass_of( $block_class, AbstractBlock::class ) ) {
				continue;
			}

			try {
				$block = new $block_class();

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

		return $blocks;
	}
}
