<?php
/**
 * Service container: registers and boots all plugin modules.
 *
 * @package Vist360
 */

namespace Vist360\Core;

defined( 'ABSPATH' ) || exit;

use Vist360\Domain\TourPostType;
use Vist360\Domain\Settings;
use Vist360\Rest\AnalyticsController;
use Vist360\Rest\ExportImportController;
use Vist360\Admin\Menu;
use Vist360\Frontend\Shortcode;
use Vist360\Frontend\Block;
use Vist360\Integrations\ElementorWidget;

/**
 * Main plugin container.
 */
final class Plugin {

	/**
	 * Singleton instance.
	 *
	 * @var Plugin|null
	 */
	private static $instance = null;

	/**
	 * Booted module instances, keyed by class name.
	 *
	 * @var object[]
	 */
	private $modules = array();

	/**
	 * Retrieve the singleton instance.
	 *
	 * @return Plugin
	 */
	public static function instance() {
		if ( null === self::$instance ) {
			self::$instance = new self();
			self::$instance->boot();
		}
		return self::$instance;
	}

	/**
	 * Retrieve a booted module by class name.
	 *
	 * @param string $class_name Fully qualified class name.
	 * @return object|null
	 */
	public function get( $class_name ) {
		return $this->modules[ $class_name ] ?? null;
	}

	/**
	 * Instantiate and boot every module.
	 */
	private function boot() {
		$module_classes = array(
			TourPostType::class,
			Settings::class,
			AnalyticsController::class,
			ExportImportController::class,
			Menu::class,
			Shortcode::class,
			Block::class,
		);

		if ( defined( 'ELEMENTOR_VERSION' ) || did_action( 'elementor/loaded' ) ) {
			$module_classes[] = ElementorWidget::class;
		}

		/**
		 * Filters the module classes booted by the plugin.
		 *
		 * @since 1.0.0
		 *
		 * @param string[] $module_classes Fully qualified class names.
		 */
		$module_classes = apply_filters( 'vist360_modules', $module_classes );

		foreach ( $module_classes as $module_class ) {
			$module = new $module_class();
			$module->register_hooks();
			$this->modules[ $module_class ] = $module;
		}

		add_action( 'init', array( Installer::class, 'maybe_upgrade' ), 5 );

		/**
		 * Fires after all plugin modules are booted.
		 *
		 * @since 1.0.0
		 *
		 * @param Plugin $plugin Plugin instance.
		 */
		do_action( 'vist360_init', $this );
	}
}
