<?php

namespace TotalTheme;

defined( 'ABSPATH' ) || exit;

/**
 * Adds custom CSS to the site from Customizer settings.
 */
final class Inline_CSS {

	/**
	 * Static only class.
	 */
	private function __construct() {}

	/**
	 * Init.
	 */
	public static function init() {

		/**
		 * Add custom CSS to head tag
		 * 
		 * @note We need extra data attributes added to the style tag so we don't use wp_add_inline_style.
		 */
		add_action( 'wp_head', [ self::class, 'on_wp_head' ], 9999 );

		/**
		 * Minify WP custom CSS on frontend.
		 *
		 * Note: We can't minify on backend or it messes up the Custom CSS panel.
		 */
		if ( ! is_admin() && ! is_customize_preview() && apply_filters( 'wpex_minify_inline_css', true ) ) {
			add_filter( 'wp_get_custom_css', [ self::class, 'minify_css' ] );
		}
	}

	/**
	 * Ouput all inline CSS into the WP Header.
	 */
	public static function on_wp_head(): void {
		$css = '';

		/**
		 * Hook: totaltheme/inline_css
		 *
		 * @todo Update all functions that hook into "wpex_head_css" filter to instead hook into here.
		 */
		if ( has_action( 'totaltheme/inline_css' ) ) {
			ob_start();
				do_action( 'totaltheme/inline_css' );
			$css_action = ob_get_clean();
			if ( $css_action && is_string( $css_action ) ) {
				$css .= $css . trim( $css_action );
			}
		}

		$css = (string) apply_filters( 'wpex_head_css', $css );

		/**
		 * Custom CSS panel => Add last after all filters to make sure it always overrides.
		 *
		 * @deprecated The theme uses native WP additional css since v4.0
		 */
		if ( $custom_css = (string) get_theme_mod( 'custom_css', null ) ) {
			$css .= "/*CUSTOM CSS*/{$custom_css}";
		}

		// Minify and output CSS in the wp_head
		if ( empty( $css ) || ! is_string( $css ) ) {
			return;
		}

		// Minify CSS
		$css = self::minify_css( $css );

		/**
		 * Sanitize CSS
		 *
		 * @important - we don't use esc_attr() because it breaks quotes in custom fonts.
		 */
		$css = (string) wp_strip_all_tags( $css );

		/**
		 * Echo CSS
		 *
		 * @important Don't rename #wpex-css or things will break!!!
		 */
		if ( $css ) {
			echo '<style data-type="wpex-css" id="wpex-css">' . trim( $css ) . '</style>';
		}
	}

	/**
	 * Minify CSS.
	 */
	public static function minify_css( string $css ): string {
		// Normalize whitespace
		$css = preg_replace( '/\s+/', ' ', $css );
		// Remove space after , : ; { } */ >
		$css = preg_replace( '/(,|:|;|\{|}|\*\/|>) /', '$1', $css );
		// Remove space before , ; { }
		$css = preg_replace( '/ (,|;|\{|})/', '$1', $css );
		// Trim white space at start and end
		$css = trim( $css );
		// return CSS
		return $css;
	}

}
