<?php
/**
 * Main plugin bootstrap.
 *
 * @package MarkBlocks
 */

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

/**
 * Registers MarkBlocks with Elementor.
 */
final class MarkBlocks_Plugin {
	/**
	 * Singleton instance.
	 *
	 * @var MarkBlocks_Plugin|null
	 */
	private static $instance = null;

	/**
	 * Return the singleton instance.
	 */
	public static function instance(): self {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}

		return self::$instance;
	}

	/**
	 * Register the delayed bootstrap callback.
	 */
	private function __construct() {
		add_action( 'plugins_loaded', [ $this, 'bootstrap' ], 20 );
	}

	/**
	 * Load the addon only after a compatible Elementor version is ready.
	 */
	public function bootstrap(): void {
		// WordPress handles the dependency through the Requires Plugins header.
		// These checks remain as defensive guards for incomplete or old installs.
		if ( ! did_action( 'elementor/loaded' ) ) {
			return;
		}

		if (
			! defined( 'ELEMENTOR_VERSION' ) ||
			version_compare( ELEMENTOR_VERSION, '3.20.0', '<' )
		) {
			return;
		}

		require_once MARKBLOCKS_PATH . 'includes/class-markblocks-markdown-parser.php';

		add_action( 'elementor/elements/categories_registered', [ $this, 'register_category' ] );
		add_action( 'elementor/widgets/register', [ $this, 'register_widgets' ] );
		add_action( 'elementor/frontend/after_register_scripts', [ $this, 'register_frontend_scripts' ] );
		add_action( 'elementor/frontend/after_register_styles', [ $this, 'register_frontend_styles' ] );
		add_action( 'elementor/editor/after_enqueue_scripts', [ $this, 'enqueue_editor_assets' ] );
		add_action( 'elementor/editor/after_enqueue_styles', [ $this, 'enqueue_editor_styles' ] );
	}

	/**
	 * Register the Elementor widget category.
	 *
	 * @param object $elements_manager Elementor elements manager.
	 */
	public function register_category( $elements_manager ): void {
		$elements_manager->add_category(
			'markblocks-content',
			[
				'title' => esc_html__( 'MarkBlocks', 'markblocks' ),
				'icon'  => 'eicon-editor-code',
			]
		);
	}

	/**
	 * Register MarkBlocks widgets.
	 *
	 * @param object $widgets_manager Elementor widget manager.
	 */
	public function register_widgets( $widgets_manager ): void {
		require_once MARKBLOCKS_PATH . 'widgets/class-markblocks-markdown-article-widget.php';
		require_once MARKBLOCKS_PATH . 'widgets/class-markblocks-code-block-widget.php';

		$widgets_manager->register( new MarkBlocks_Markdown_Article_Widget() );
		$widgets_manager->register( new MarkBlocks_Code_Block_Widget() );
	}

	/**
	 * Register frontend scripts. Elementor enqueues them only for widgets that
	 * declare the handles through get_script_depends().
	 */
	public function register_frontend_scripts(): void {
		wp_register_script(
			'markblocks-syntax-highlighter',
			MARKBLOCKS_URL . 'assets/js/syntax-highlighter.js',
			[],
			MARKBLOCKS_VERSION,
			true
		);

		wp_register_script(
			'markblocks-frontend',
			MARKBLOCKS_URL . 'assets/js/frontend.js',
			[ 'markblocks-syntax-highlighter' ],
			MARKBLOCKS_VERSION,
			true
		);

		wp_localize_script(
			'markblocks-frontend',
			'MARKBLOCKS_FRONTEND',
			[
				'copied' => esc_html__( 'Copied', 'markblocks' ),
			]
		);
	}

	/**
	 * Register frontend styles for conditional Elementor loading.
	 */
	public function register_frontend_styles(): void {
		wp_register_style(
			'markblocks-frontend',
			MARKBLOCKS_URL . 'assets/css/frontend.css',
			[],
			MARKBLOCKS_VERSION
		);
	}

	/**
	 * Enqueue the Markdown-to-Elementor converter in the Elementor editor only.
	 */
	public function enqueue_editor_assets(): void {
		if ( ! wp_script_is( 'markblocks-syntax-highlighter', 'registered' ) ) {
			$this->register_frontend_scripts();
		}

		wp_enqueue_script(
			'markblocks-editor-converter',
			MARKBLOCKS_URL . 'assets/js/editor-converter.js',
			[ 'jquery', 'elementor-editor', 'markblocks-syntax-highlighter' ],
			MARKBLOCKS_VERSION,
			true
		);

		wp_localize_script(
			'markblocks-editor-converter',
			'MARKBLOCKS_EDITOR',
			[
				'widgetType'         => 'emb_markdown_article',
				'codeWidgetType'     => 'emb_code_block',
				'converting'         => esc_html__( 'Converting Markdown…', 'markblocks' ),
				'converted'          => esc_html__( 'Elementor blocks created. Update the page to save them.', 'markblocks' ),
				'updated'            => esc_html__( 'Previous imported blocks were replaced.', 'markblocks' ),
				'wrongWidget'        => esc_html__( 'Select the Markdown Article widget and try again.', 'markblocks' ),
				'emptyMarkdown'      => esc_html__( 'Paste Markdown before converting.', 'markblocks' ),
				'unsupportedEditor'  => esc_html__( 'The current Elementor editor did not expose the selected widget container.', 'markblocks' ),
				'tooManyBlocks'      => esc_html__( 'The article contains too many blocks for one conversion. Split it into smaller Markdown widgets.', 'markblocks' ),
				'tooLarge'           => esc_html__( 'The Markdown source exceeds the 2 MB safety limit. Split it into smaller Markdown widgets.', 'markblocks' ),
				'tooManyLines'       => esc_html__( 'The Markdown source exceeds the 50,000-line safety limit. Split it into smaller Markdown widgets.', 'markblocks' ),
				'generatedTitle'     => esc_html__( 'Imported Markdown Article', 'markblocks' ),
				'createFailed'       => esc_html__( 'Elementor did not return the generated container.', 'markblocks' ),
				'sourceUpdateFailed' => esc_html__( 'The Markdown source widget could not be updated.', 'markblocks' ),
				'maxMarkdownBytes'   => MarkBlocks_Markdown_Parser::max_markdown_bytes(),
				'maxMarkdownLines'   => MarkBlocks_Markdown_Parser::max_markdown_lines(),
				'failed'             => esc_html__( 'Conversion failed:', 'markblocks' ),
			]
		);
	}

	/**
	 * Enqueue editor-only styles.
	 */
	public function enqueue_editor_styles(): void {
		wp_enqueue_style(
			'markblocks-editor',
			MARKBLOCKS_URL . 'assets/css/editor.css',
			[],
			MARKBLOCKS_VERSION
		);
	}
}
