<?php
/**
 * Editor Hooks Class
 *
 * @package errigal
 * @since 1.1.0
 */

namespace Errigal\Hook;

defined( 'ABSPATH' ) || exit;

use Errigal\Constant\Errigal_WP_Hook as WP_Hook;
use Errigal\Customiser\Errigal_Custom_Typography as Typography;
use Errigal\Shared\{
	Errigal_Asset as Asset,
	Errigal_Utility as Utility,
	Errigal_Validator as Validator,
};

/**
 * This class is in charge of adding editor hooks.
 *
 * @since 1.1.0
 */
class Errigal_Editor_Hooks extends Errigal_Hooks_Base {
	/**
	 * Indicates current context is editor.
	 *
	 * @since 1.1.0
	 *
	 * @var bool
	 */
	private const IS_EDITOR = true;

	/**
	 * TinyMCE config: Content style.
	 *
	 * @since 1.1.0
	 *
	 * @var string
	 */
	private const MCE_CONTENT_STYLE = 'content_style';

	/**
	 * Enqueues editor style.
	 *
	 * @since 1.0.0
	 *
	 * @link https://developer.wordpress.org/reference/hooks/admin_init/
	 *
	 * @return void
	 */
	public function enqueue_editor_style() {
		add_editor_style( Asset::get_editor_stylesheet_uri() );
	}

	/**
	 * Enqueues block editor font styles.
	 *
	 * @since 1.0.0
	 *
	 * @link https://developer.wordpress.org/reference/hooks/enqueue_block_editor_assets/
	 *
	 * @return void
	 */
	public function enqueue_block_editor_font_styles() {
		if ( is_customize_preview() ) {
			return;
		}

		$editor_style_base_google_font = $this->get_editor_style_handle( Typography::STYLE_BASE_GOOGLE_FONT );

		Asset::enqueue_style(
			$editor_style_base_google_font,
			Typography::get_base_font_uri( self::IS_EDITOR )
		);

		Asset::add_inline_style(
			$editor_style_base_google_font,
			Typography::get_base_inline_font_style( self::IS_EDITOR )
		);

		if ( ! Typography::has_unique_heading_font() ) {
			return;
		}

		$editor_style_heading_google_font = $this->get_editor_style_handle( Typography::STYLE_HEADING_GOOGLE_FONT );

		Asset::enqueue_style(
			$editor_style_heading_google_font,
			Typography::get_heading_font_uri( self::IS_EDITOR )
		);

		Asset::add_inline_style(
			$editor_style_heading_google_font,
			Typography::get_heading_inline_font_style( self::IS_EDITOR )
		);
	}

	/**
	 * Enqueues classic editor font styles.
	 *
	 * @since 1.0.0
	 *
	 * @link https://developer.wordpress.org/reference/hooks/admin_init/
	 *
	 * @return void
	 */
	public function enqueue_classic_editor_font_styles() {
		add_editor_style( Typography::get_base_font_uri( self::IS_EDITOR ) );

		if ( ! Typography::has_unique_heading_font() ) {
			return;
		}

		add_editor_style( Typography::get_heading_font_uri( self::IS_EDITOR ) );
	}

	/**
	 * Enqueues classic editor inline font styles.
	 *
	 * @since 1.0.0
	 *
	 * @link https://developer.wordpress.org/reference/hooks/tiny_mce_before_init/
	 *
	 * @param array $mce_init Associative array of arguments for TinyMCE.
	 * @return array
	 */
	public function enqueue_classic_editor_inline_font_styles( $mce_init ) {
		if ( Validator::is_associative_array( $mce_init ) ) {
			$mce_init = wp_parse_args(
				$mce_init,
				array(
					self::MCE_CONTENT_STYLE => '',
				)
			);

			$inline_font_style = Typography::get_base_inline_font_style( self::IS_EDITOR );

			if ( Typography::has_unique_heading_font() ) {
				$inline_font_style .= Typography::get_heading_inline_font_style( self::IS_EDITOR );
			}

			$mce_init[ self::MCE_CONTENT_STYLE ] = str_replace(
				'"',
				"'",
				$inline_font_style
			);
		}

		return $mce_init;
	}

	/**
	 * Enqueues block editor script.
	 *
	 * @since 1.1.0
	 *
	 * @link https://developer.wordpress.org/reference/hooks/enqueue_block_editor_assets/
	 *
	 * @return void
	 */
	public function enqueue_block_editor_script() {
		Asset::enqueue_script(
			Asset::EDITOR,
			array(
				Asset::DEP_SCRIPT_WP_BLOCKS,
				Asset::DEP_SCRIPT_WP_DOM,
			)
		);
	}

	/**
	 * Adds hooks.
	 *
	 * @since 1.1.0
	 *
	 * @return void
	 */
	protected function add_hooks() {
		$this->add_editor_style_hooks();
		$this->add_block_editor_style_hooks();
		$this->add_classic_editor_style_hooks();

		$this->add_block_editor_script_hooks();
	}

	/**
	 * Adds editor style hooks.
	 *
	 * @since 1.1.0
	 *
	 * @return void
	 */
	private function add_editor_style_hooks() {
		add_action( WP_Hook::ADMIN_INIT, array( $this, 'enqueue_editor_style' ) );
	}

	/**
	 * Adds block editor style hooks.
	 *
	 * @since 1.1.0
	 *
	 * @return void
	 */
	private function add_block_editor_style_hooks() {
		add_action( WP_Hook::ENQUEUE_BLOCK_EDITOR_ASSETS, array( $this, 'enqueue_block_editor_font_styles' ) );
	}

	/**
	 * Adds classic editor style hooks.
	 *
	 * @since 1.1.0
	 *
	 * @return void
	 */
	private function add_classic_editor_style_hooks() {
		add_filter( WP_Hook::ADMIN_INIT, array( $this, 'enqueue_classic_editor_font_styles' ) );
		add_filter( WP_Hook::TINY_MCE_BEFORE_INIT, array( $this, 'enqueue_classic_editor_inline_font_styles' ) );
	}

	/**
	 * Adds block editor script hooks.
	 *
	 * @since 1.1.0
	 *
	 * @return void
	 */
	private function add_block_editor_script_hooks() {
		add_action( WP_Hook::ENQUEUE_BLOCK_EDITOR_ASSETS, array( $this, 'enqueue_block_editor_script' ) );
	}

	/**
	 * Gets editor style handle.
	 *
	 * @since 1.1.0
	 *
	 * @param string $style Stylesheet name.
	 * @return string
	 */
	private function get_editor_style_handle( $style ) {
		if ( ! Validator::is_non_empty_string( $style ) ) {
			return '';
		}

		return sanitize_key(
			Utility::join(
				Utility::SEPARATOR_HYPHEN,
				Asset::EDITOR,
				$style
			)
		);
	}
}
