<?php
/**
 * Add Google Fonts dropdown to the classic editor.
 *
 * @package   olympus-google-fonts
 * @copyright Copyright (c) 2020, Fonts Plugin
 * @license   http://opensource.org/licenses/gpl-2.0.php GNU Public License
 */

if ( ! class_exists( 'OGF_Classic_Editor' ) ) :
	/**
	 * The 'Classic Editor' class.
	 */
	class OGF_Classic_Editor {

		/**
		 * OGF_Fonts object.
		 *
		 * @var object
		 */
		private $ogf_fonts;

		/**
		 * Array of system fonts.
		 *
		 * @var array
		 */
		private $system_fonts;

		/**
		 * Array of custom fonts.
		 *
		 * @var array
		 */
		private $custom_fonts;

		/**
		 * Array of typekit fonts.
		 *
		 * @var array
		 */
		private $typekit_fonts;

		/**
		 * Class constructor.
		 */
		public function __construct() {
			if ( true === get_theme_mod( 'ogf_disable_post_level_controls', false ) ) {
				return;
			}

			$this->ogf_fonts     = OGF_Fonts::get_instance();
			$this->system_fonts  = ogf_system_fonts();
			$this->custom_fonts  = ogf_custom_fonts();
			$this->typekit_fonts = ogf_typekit_fonts();

			add_filter( 'tiny_mce_before_init', array( $this, 'add_font_sizes' ) );
			add_filter( 'mce_buttons', array( $this, 'tinymce_add_buttons' ), 1 );
			add_filter( 'tiny_mce_before_init', array( $this, 'tinymce_custom_options' ), 100 );
			add_filter( 'ogf_classic_font_formats', array( $this, 'tinymce_add_fonts' ), 100 );

			// Push editor styles now: we may bootstrap on current_screen (after admin_init).
			$this->google_fonts_enqueue();
			$this->typekit_fonts_enqueue();
		}

		/**
		 * Add Formats to TinyMCE
		 * - https://developer.wordpress.org/reference/hooks/tiny_mce_before_init/
		 * - https://codex.wordpress.org/Plugin_API/Filter_Reference/tiny_mce_before_init
		 *
		 * @param array $args Arguments used to initialize the tinyMCE.
		 *
		 * @return array $args Modified arguments.
		 */
		public function add_font_sizes( $args ) {
			if ( true === get_theme_mod( 'ogf_use_px', true ) ) {
				$args['fontsize_formats'] = '6px 7px 8px 9px 10px 11px 12px 13px 14px 15px 16px 17px 18px 19px 20px 21px 22px 23px 24px 25px 26px 27px 28px 29px 30px 31px 32px 33px 34px 35px 36px 37px 38px 39px 40px 41px 42px 43px 44px 45px 46px 47px 48px 49px 50px 51px 52px 53px 55px 55px 56px 57px 58px 59px 60px 61px 62px 63px 66px 65px 66px 67px 68px 69px 70px 71px 72px 73px 77px 75px 76px 77px 78px 79px 80px';
			}

			return apply_filters( 'ogf_classic_font_sizes', $args );
		}

		/**
		 * Add buttons to the editor.
		 *
		 * @param array $buttons Tiny MCE buttons array.
		 * @return array Modified Tiny MCE buttons array.
		 */
		public function tinymce_add_buttons( $buttons ) {
			return array_merge(
				array( 'fontselect', 'fontsizeselect' ),
				$buttons
			);
		}

		/**
		 * Customize the Tiny MCE settings.
		 *
		 * @param array $opt Tiny MCE options.
		 * @return array Modified Tiny MCE options.
		 */
		public function tinymce_custom_options( $opt ) {
			$base_type             = get_theme_mod( 'ogf_body_font' );
			$base_font_size        = get_theme_mod( 'ogf_body_font_size', false );
			$base_font_weight      = get_theme_mod( 'ogf_body_font_weight', false );
			$base_font_line_height = get_theme_mod( 'ogf_body_line_height', false );

			$content_type             = get_theme_mod( 'ogf_post_page_content_font' );
			$content_font_size        = get_theme_mod( 'ogf_post_page_content_font_size', false );
			$content_font_weight      = get_theme_mod( 'ogf_post_page_content_font_weight', false );
			$content_font_line_height = get_theme_mod( 'ogf_post_page_content_line_height', false );

			$headings_type        = get_theme_mod( 'ogf_headings_font' );
			$headings_font_weight = get_theme_mod( 'ogf_headings_font_weight', false );

			if ( ogf_is_custom_font( $base_type ) ) {
				$name      = str_replace( 'cf-', '', $base_type );
				$font      = OGF_Fonts_Taxonomy::get_by_name( $name );
				$base_type = ! empty( $font['family'] ) ? $font['family'] : $name;
			} elseif ( ogf_is_system_font( $base_type ) ) {
				$base_type = str_replace( 'sf-', '', $base_type );
				$base_type = $this->system_fonts[ $base_type ]['stack'] ?? $base_type;
			} elseif ( ogf_is_google_font( $base_type ) ) {
				$base_type = $this->ogf_fonts->get_font_name( $base_type );
			} elseif ( ogf_is_typekit_font( $base_type ) ) {
				$base_type = $this->typekit_fonts[ $base_type ]['stack'] ?? $base_type;
			}

			if ( ogf_is_custom_font( $content_type ) ) {
				$name         = str_replace( 'cf-', '', $content_type );
				$font         = OGF_Fonts_Taxonomy::get_by_name( $name );
				$content_type = ! empty( $font['family'] ) ? $font['family'] : $name;
			} elseif ( ogf_is_system_font( $content_type ) ) {
				$content_type = str_replace( 'sf-', '', $content_type );
				$content_type = $this->system_fonts[ $content_type ]['stack'] ?? $content_type;
			} elseif ( ogf_is_google_font( $content_type ) ) {
				$content_type = $this->ogf_fonts->get_font_name( $content_type );
			} elseif ( ogf_is_typekit_font( $content_type ) ) {
				$content_type = $this->typekit_fonts[ $content_type ]['stack'] ?? $content_type;
			}

			if ( ogf_is_custom_font( $headings_type ) ) {
				$name          = str_replace( 'cf-', '', $headings_type );
				$font          = OGF_Fonts_Taxonomy::get_by_name( $name );
				$headings_type = ! empty( $font['family'] ) ? $font['family'] : $name;
			} elseif ( ogf_is_system_font( $headings_type ) ) {
				$headings_type = str_replace( 'sf-', '', $headings_type );
				$headings_type = $this->system_fonts[ $headings_type ]['stack'] ?? $headings_type;
			} elseif ( ogf_is_google_font( $headings_type ) ) {
				$headings_type = $this->ogf_fonts->get_font_name( $headings_type );
			} elseif ( ogf_is_typekit_font( $headings_type ) ) {
				$headings_type = $this->typekit_fonts[ $headings_type ]['label'] ?? $headings_type;
			}

			$opt['font_formats'] = apply_filters( 'ogf_classic_font_formats', 'Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;' );

			if ( ! isset( $opt['content_style'] ) ) {
				$opt['content_style'] = '';
			}

			$opt['content_style'] .= 'body#tinymce, body#tinymce p { ';

			if ( $base_type !== 'default' ) {
				$opt['content_style'] .= ' font-family: ' . str_replace( '"', '\'', $base_type ) . ' !important;';
			}
			if ( $base_font_size ) {
				$opt['content_style'] .= ' font-size: ' . $base_font_size . 'px !important;';
			}
			if ( $base_font_weight ) {
				$opt['content_style'] .= ' font-weight: ' . $base_font_weight . ' !important;';
			}
			if ( $base_font_line_height ) {
				$opt['content_style'] .= ' line-height: ' . $base_font_line_height . ' !important;';
			}

			if ( $content_type !== 'default' ) {
				$opt['content_style'] .= ' font-family: ' . str_replace( '"', '\'', $content_type ) . ' !important;';
			}
			if ( $content_font_size ) {
				$opt['content_style'] .= ' font-size: ' . $content_font_size . 'px !important;';
			}
			if ( $content_font_weight ) {
				$opt['content_style'] .= ' font-weight: ' . $content_font_weight . ' !important;';
			}
			if ( $content_font_line_height ) {
				$opt['content_style'] .= ' line-height: ' . $content_font_line_height . ' !important;';
			}

			$opt['content_style'] .= '}';

			$opt['content_style'] .= '#tinymce h1, #tinymce h2, #tinymce h3, #tinymce h4, #tinymce h5, #tinymce h6 {';

			if ( $headings_type !== 'default' ) {
				$opt['content_style'] .= ' font-family: ' . str_replace( '"', '\'', $headings_type ) . ' !important;';
			}
			if ( $headings_font_weight ) {
				$opt['content_style'] .= ' font-weight: ' . $headings_font_weight . ' !important;';
			}

			$opt['content_style'] .= '}';

			$opt['content_style'] .= ogf_return_custom_font_css();
			return $opt;
		}

		/**
		 * Add fonts to the classic editor list.
		 *
		 * @param string $old_default The default fonts.
		 * @return string Modified fonts string.
		 */
		public function tinymce_add_fonts( $old_default ) {
			$new_default = '';
			$choices     = $this->ogf_fonts->choices;
			// Same font ID can appear more than once in $choices (different elements reuse one face).
			// Keys here are font IDs we already appended to TinyMCE's format string — skip repeats.
			$seen_choice = array();
			foreach ( $choices as $font ) {
				if ( isset( $seen_choice[ $font ] ) ) {
					continue;
				}
				$seen_choice[ $font ] = true;
				if ( ogf_is_google_font( $font ) ) {
					$name = $this->ogf_fonts->get_font_name( $font );
					$new_default .= $name . '=' . $name . ';';
				}
			}

			foreach ( $this->custom_fonts as $font ) {
				$stack = ! empty( $font['family'] ) ? $font['family'] : $font['stack'];

				$new_default .= $font['label'] . '=' . $stack . ';';
			}

			foreach ( $this->typekit_fonts as $font ) {
				$new_default .= $font['label'] . '=' . str_replace( '"', '', $font['stack'] ) . ';';
			}

			$new_default .= $old_default;
			return $new_default;
		}

		/**
		 * Enqueue the Google Fonts in TinyMCE.
		 */
		public function google_fonts_enqueue() {
			global $editor_styles;
			if ( $this->ogf_fonts->has_google_fonts() ) {
				// phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Adding to editor styles is the standard pattern.
				$editor_styles[] = $this->ogf_fonts->build_url();
			}
		}

		/**
		 * Enqueue the Typekit Fonts in TinyMCE.
		 */
		public function typekit_fonts_enqueue() {
			global $editor_styles;

			$typekit_data = get_option( 'fp-typekit-data', array() );

			if ( is_array( $typekit_data ) ) {
				foreach ( $typekit_data as $id => $values ) {
					// skip if the kit is disabled.
					if ( $values['enabled'] === false ) {
						continue;
					}

					// phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Adding to editor styles is the standard pattern.
					$editor_styles[] = esc_url( 'https://use.typekit.com/' . $id . '.css' );
				}
			}
		}
	}
endif;

/**
 * Whether the current admin screen should load Classic / TinyMCE integration.
 *
 * @param WP_Screen $screen Current screen.
 * @return bool
 */
function ogf_screen_needs_classic_editor_integration( $screen ) {
	if ( ! $screen instanceof WP_Screen ) {
		return false;
	}

	/**
	 * Short-circuit Classic Editor integration for a screen.
	 *
	 * @param bool|null $load   Return true to force load, false to skip, null to use default logic.
	 * @param WP_Screen $screen Current screen.
	 */
	$forced = apply_filters( 'ogf_load_classic_editor_integration', null, $screen );
	if ( true === $forced ) {
		return true;
	}
	if ( false === $forced ) {
		return false;
	}

	// Post / page / CPT screens: only when the block editor is not used for this post type.
	if ( 'post' === $screen->base ) {
		$post_type = $screen->post_type;
		if ( empty( $post_type ) ) {
			return true;
		}
		if ( function_exists( 'use_block_editor_for_post_type' ) ) {
			return ! use_block_editor_for_post_type( $post_type );
		}
		return true;
	}

	// Legacy widgets screen (TinyMCE in text widgets).
	if ( 'widgets' === $screen->id ) {
		return true;
	}

	return false;
}

/**
 * Load Classic Editor integration only when needed (skip front-end and most admin screens).
 *
 * @return void
 */
function ogf_init_classic_editor_integration() {
	if ( true === get_theme_mod( 'ogf_disable_post_level_controls', false ) ) {
		return;
	}

	if ( ! is_admin() ) {
		return;
	}

	static $registered = false;
	if ( $registered ) {
		return;
	}
	$registered = true;

	// admin-ajax.php does not run set_current_screen(); keep previous behavior for AJAX.
	if ( wp_doing_ajax() ) {
		new OGF_Classic_Editor();
		return;
	}

	add_action(
		'current_screen',
		static function ( $screen ) {
			static $booted = false;
			if ( $booted ) {
				return;
			}
			if ( ! ogf_screen_needs_classic_editor_integration( $screen ) ) {
				return;
			}
			$booted = true;
			new OGF_Classic_Editor();
		},
		0
	);
}
add_action( 'admin_init', 'ogf_init_classic_editor_integration', 0 );
