<?php
/**
 * Image Object Position Block Settings
 * Adds object-position (focal point) control to image blocks when scale=cover
 *
 * @package Brandy\BlockSettings\ImageObjectPosition
 */

namespace Brandy\BlockSettings\ImageObjectPosition;

use Brandy\Traits\SingletonTrait;
use Brandy\Interfaces\ExternalBlockSettingsInterface;

class Caller implements ExternalBlockSettingsInterface {
	use SingletonTrait;

	protected $supported_blocks = array(
		'core/image',
		'woocommerce/product-image',
		'core/post-featured-image',
	);

	protected function __construct() {
		add_filter( 'block_type_metadata_settings', array( $this, 'declare_attribute' ), 10 );
		add_action( 'enqueue_block_editor_assets', array( $this, 'enqueue_settings_scripts' ) );

		foreach ( $this->supported_blocks as $block ) {
			add_filter( 'render_block_' . $block, array( $this, 'apply_object_position' ), 20, 2 );
		}
	}

	private function is_supported( $name ) {
		return in_array( $name, $this->supported_blocks, true );
	}

	/**
	 * Register objectPosition attribute for supported blocks
	 */
	public function declare_attribute( $settings ) {
		if ( empty( $settings['name'] ) || ! $this->is_supported( $settings['name'] ) ) {
			return $settings;
		}

		if ( ! empty( $settings['attributes'] ) ) {
			$settings['attributes']['objectPosition'] = array(
				'type' => 'object',
			);
		}

		return $settings;
	}

	public function enqueue_settings_scripts() {
		wp_enqueue_script(
			'brandy/image-object-position',
			BRANDY_TEMPLATE_URL . '/inc/BlockSettings/ImageObjectPosition/script.js',
			array( 'wp-edit-post', 'wp-blocks', 'wp-element', 'wp-components', 'wp-block-editor', 'wp-compose', 'wp-hooks', 'wp-i18n', 'wp-data' ),
			BRANDY_SCRIPT_VERSION,
			true
		);
	}

	/**
	 * Convert objectPosition {x, y} to CSS percentage string
	 *
	 * @param array $object_position The position object with x and y values (0-1 range).
	 * @return string CSS object-position value like "50% 30%".
	 */
	public static function get_position_css( $object_position ) {
		$x = isset( $object_position['x'] ) ? floatval( $object_position['x'] ) : 0.5;
		$y = isset( $object_position['y'] ) ? floatval( $object_position['y'] ) : 0.5;
		$x = max( 0, min( 1, $x ) );
		$y = max( 0, min( 1, $y ) );
		return round( $x * 100 ) . '% ' . round( $y * 100 ) . '%';
	}

	/**
	 * Apply object-position CSS to rendered image blocks
	 */
	public function apply_object_position( $html, $block ) {
		$attrs           = $block['attrs'] ?? array();
		$object_position = $attrs['objectPosition'] ?? null;
		$scale           = $attrs['scale'] ?? '';

		if ( empty( $object_position ) || 'cover' !== $scale ) {
			return $html;
		}

		$position_value = self::get_position_css( $object_position );

		$tag = new \WP_HTML_Tag_Processor( $html );
		if ( $tag->next_tag( 'img' ) ) {
			$existing_style = $tag->get_attribute( 'style' ) ?? '';
			if ( ! empty( $existing_style ) && ! str_ends_with( $existing_style, ';' ) ) {
				$existing_style .= ';';
			}
			$tag->set_attribute( 'style', $existing_style . 'object-position:' . $position_value );
		}

		return $tag->get_updated_html();
	}
}

Caller::get_instance();
