<?php

namespace Brandy\BlockSettings\DisplaySettings;

use Brandy\Traits\SingletonTrait;

class Caller {

	use SingletonTrait;

	/**
	 * Track if frontend styles already enqueued.
	 *
	 * @var bool
	 */
	private $frontend_styles_enqueued = false;

	protected function __construct() {
		add_action( 'enqueue_block_editor_assets', array( $this, 'enqueue_editor_assets' ) );
		add_action( 'enqueue_block_assets', array( $this, 'enqueue_editor_styles' ) );
		add_filter( 'render_block', array( $this, 'add_display_style_attribute' ), 10, 3 );
		add_filter( 'block_type_metadata_settings', array( $this, 'declare_attribute' ), 10 );
	}

	public function declare_attribute( $settings ) {
		if ( ! empty( $settings['attributes'] ) ) {
			$settings['attributes']['displaySettings'] = array(
				'type'    => 'object',
				'default' => array(
					'key'  => 'default',
					'name' => 'Default',
				),
			);
		}
		return $settings;
	}

	public function enqueue_editor_assets() {
		wp_enqueue_script(
			'brandy/display-settings-controls',
			BRANDY_TEMPLATE_URL . '/inc/BlockSettings/DisplaySettings/script.js',
			array( 'wp-edit-post', 'wp-element', 'wp-compose', 'wp-blocks', 'wp-hooks', 'wp-i18n', 'wp-components', 'wp-block-editor', 'wp-data' ),
			BRANDY_SCRIPT_VERSION,
			true
		);
	}

	public function enqueue_editor_styles() {
		$this->maybe_enqueue_frontend_styles( true );
	}

	public function maybe_enqueue_frontend_styles( $admin_enqueue = false ) {

		if ( ! $admin_enqueue && is_admin() ) {
			return;
		}

		if ( $admin_enqueue && ! is_admin() ) {
			return;
		}

		if ( $this->frontend_styles_enqueued ) {
			return;
		}
		$this->frontend_styles_enqueued = true;
		wp_register_style( 'brandy/display-settings-style', false );
		wp_enqueue_style( 'brandy/display-settings-style' );
		wp_add_inline_style( 'brandy/display-settings-style', $this->get_css() );
	}

	public function get_css() {
		ob_start();
		?>
		.is-relative-position {
		position: relative !important;
		}
		.is-absolute-position {
		position: absolute !important;
		}
		.is-absolute-position,
		.is-relative-position {
		top: var(--top, auto) !important;
		bottom: var(--bottom, auto) !important;
		left: var(--left, auto) !important;
		right: var(--right, auto) !important;
		z-index: 10 !important;
		}
		.is-absolute-position {
		width: var(--width, auto) !important;
		height: var(--height, auto) !important;
		}
		<?php
		return ob_get_clean();
	}

	public function add_display_style_attribute( $block_content, $block, $instance ) {

		if ( empty( $block['attrs'] ) ) {
			return $block_content;
		}

		$attributes = (array) $block['attrs'];

		if ( empty( $attributes ) ) {
			return $block_content;
		}

		$display_settings = isset( $attributes['displaySettings'] ) ? $attributes['displaySettings'] : array();

		if ( empty( $display_settings ) ) {
			return $block_content;
		}

		$position = isset( $display_settings['key'] ) ? $display_settings['key'] : '';

		if ( 'default' === $position ) {
			return $block_content;
		}

		$style = '';
		$class = '';

		if ( 'relative' === $position || 'absolute' === $position ) {
			$class      = "is-{$position}-position ";
			$dimensions = isset( $display_settings['dimensions'] ) ? $display_settings['dimensions'] : array();

			if ( ! empty( $dimensions ) ) {
				$top    = isset( $dimensions['top'] ) ? self::get_spacing_preset_css_var( $dimensions['top'] ) : '';
				$bottom = isset( $dimensions['bottom'] ) ? self::get_spacing_preset_css_var( $dimensions['bottom'] ) : '';
				$left   = isset( $dimensions['left'] ) ? self::get_spacing_preset_css_var( $dimensions['left'] ) : '';
				$right  = isset( $dimensions['right'] ) ? self::get_spacing_preset_css_var( $dimensions['right'] ) : '';

				if ( $top ) {
					$style .= '--top: ' . $top . ';';
				}
				if ( $bottom ) {
					$style .= '--bottom: ' . $bottom . ';';
				}
				if ( $left ) {
					$style .= '--left: ' . $left . ';';
				}
				if ( $right ) {
					$style .= '--right: ' . $right . ';';
				}
			}

			if ( 'absolute' === $position ) {
				$width  = $display_settings['width'] ?? '';
				$height = $display_settings['height'] ?? '';
				if ( $width ) {
					$style .= '--width: ' . $width . ';';
				}
				if ( $height ) {
					$style .= '--height: ' . $height . ';';
				}
			}
		}

		if ( $class ) {

			if ( ! is_admin() ) {
				$this->maybe_enqueue_frontend_styles();
			}

			$tags = new \WP_HTML_Tag_Processor( $block_content );
			if ( $tags->next_tag() ) {
				$existing_class = $tags->get_attribute( 'class' ) ?? '';
				$tags->set_attribute( 'class', $existing_class . ' ' . $class );

				if ( $style ) {
					$existing_style = $tags->get_attribute( 'style' ) ?? '';
					if ( ! empty( $existing_style ) ) {
						$existing_style .= ';';
					}
					$tags->set_attribute( 'style', $existing_style . $style );
				}

				$block_content = $tags->get_updated_html();
			}
		}

		return $block_content;
	}

	public static function get_spacing_preset_css_var( $value ) {
		if ( ! $value ) {
			return null;
		}

		preg_match( '/var:preset\|spacing\|(.+)/', $value, $matches );

		if ( empty( $matches ) ) {
			return $value;
		}

		return 'var(--wp--preset--spacing--' . $matches[1] . ')';
	}
}

Caller::get_instance();
