<?php
/**
 * Panorama Scene element.
 *
 * @package BricksExtras
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

/**
 * Panorama Scene element class.
 */
class X_Panorama_Scene extends \Bricks\Element {

	/**
	 * Element category.
	 *
	 * @var string
	 */
	public $category = 'extras';
	/**
	 * Element name.
	 *
	 * @var string
	 */
	public $name = 'xpanoramascene';
	/**
	 * Element icon.
	 *
	 * @var string
	 */
	public $icon = 'ti-image';
	/**
	 * CSS selector.
	 *
	 * @var string
	 */
	public $css_selector = '';
	/**
	 * Required scripts.
	 *
	 * @var array
	 */
	public $scripts = array( 'xPanoramaViewer' );
	/**
	 * Loop index.
	 *
	 * @var int
	 */
	public $loop_index = 0;
	/**
	 * Element is nestable.
	 *
	 * @var bool
	 */
	public $nestable = true;


	/**
	 * Get element label.
	 */
	public function get_label() {
		return esc_html__( 'Panorama Scene', 'bricksextras' );
	}

	/**
	 * Get element keywords.
	 */
	public function get_keywords() {
		return array( 'panorama', 'image', 'scene' );
	}

	/**
	 * Set control groups.
	 */
	public function set_control_groups() {

		$this->control_groups['hotspots'] = array(
			'title' => esc_html__( 'Hotspots', 'bricksextras' ),
			'tab'   => 'content',
		);

		$this->control_groups['viewer'] = array(
			'title' => esc_html__( 'Viewer Settings', 'bricksextras' ),
			'tab'   => 'content',
		);
	}

	/**
	 * Set element controls.
	 */
	public function set_controls() {

		// Scene ID (for tours).
		$this->controls['sceneId'] = array(
			'tab'    => 'content',
			'label'  => esc_html__( 'Scene identifier', 'bricksextras' ),
			'type'   => 'text',
			'inline' => true,
		);

		$this->controls['sceneTitle'] = array(
			'tab'    => 'content',
			'label'  => esc_html__( 'Scene title', 'bricksextras' ),
			'type'   => 'text',
			'inline' => true,
		);

		// Panorama Image.
		$this->controls['panoramaImage'] = array(
			'tab'   => 'content',
			'label' => esc_html__( 'Panorama image', 'bricksextras' ),
			'type'  => 'image',
		);

		// Query Loop.
		$this->controls['hasLoop'] = array(
			'tab'         => 'content',
			'group'       => 'hotspots',
			'label'       => esc_html__( 'Query loop', 'bricks' ),
			'type'        => 'checkbox',
			'inline'      => true,
			'description' => esc_html__( 'Populate hotspots from query results or add manually below', 'bricksextras' ),
		);

		$this->controls['query'] = array(
			'tab'      => 'content',
			'group'    => 'hotspots',
			'label'    => esc_html__( 'Query', 'bricks' ),
			'type'     => 'query',
			'popup'    => true,
			'inline'   => true,
			'required' => array( 'hasLoop', '!=', '' ),
		);

		// Hot Spots.
		$this->controls['hotSpots'] = array(
			'tab'           => 'content',
			'group'         => 'hotspots',
			'placeholder'   => esc_html__( 'Hotspots', 'bricksextras' ),
			'type'          => 'repeater',
			'titleProperty' => 'buttonText',
			'required'      => array( 'hasLoop', '=', '' ),
			'fields'        => array(
				'pitch'            => array(
					'label'       => 'Pitch',
					'type'        => 'number',
					'placeholder' => '0',
					'description' => esc_html__( 'Position', 'bricks' ) . ' (°) (' . esc_html__( 'Vertical', 'bricks' ) . ')',
				),
				'yaw'              => array(
					'label'       => 'Yaw',
					'type'        => 'number',
					'placeholder' => '0',
					'description' => esc_html__( 'Position', 'bricks' ) . ' (°) (' . esc_html__( 'Horizontal', 'bricks' ) . ')',
				),
				'icon'             => array(
					'label' => esc_html__( 'Icon', 'bricks' ),
					'type'  => 'icon',
				),
				'text'             => array(
					'label' => esc_html__( 'Content', 'bricks' ) . ' (' . esc_html__( 'Tooltip', 'bricks' ) . ')',
					'type'  => 'editor',
				),
				'buttonText'       => array(
					'label'  => esc_html__( 'Button text', 'bricks' ),
					'inline' => true,
					'type'   => 'text',
				),
				'hotspotName'      => array(
					'label'       => esc_html__( 'Hotspot name', 'bricksextras' ),
					'type'        => 'text',
					'inline'      => true,
					'description' => esc_html__( 'Unique name to link to this hotspot from tooltip content using #hotspot-name', 'bricksextras' ),
				),
				'hotspotAriaLabel' => array(
					'label'  => esc_html__( 'Aria label', 'bricksextras' ),
					'type'   => 'text',
					'inline' => true,
				),
				'type'             => array(
					'label'       => esc_html__( 'Type', 'bricks' ),
					'type'        => 'select',
					'inline'      => true,
					'options'     => array(
						'info'  => esc_html__( 'Info', 'bricks' ) . ' (' . esc_html__( 'Default', 'bricks' ) . ')',
						'scene' => esc_html__( 'Scene link', 'bricksextras' ),
						'link'  => esc_html__( 'Link', 'bricks' ),
					),
					'placeholder' => esc_html__( 'Info', 'bricks' ) . ' (' . esc_html__( 'Default', 'bricks' ) . ')',
				),
				'link'             => array(
					'label'    => esc_html__( 'Link', 'bricks' ),
					'type'     => 'link',
					'required' => array( 'type', '=', 'link' ),
				),
				'sceneId'          => array(
					'label'       => esc_html__( 'Scene identifier', 'bricksextras' ),
					'type'        => 'text',
					'placeholder' => 'scene-1',
					'required'    => array( 'type', '=', 'scene' ),
				),
			),
			'default'       => array(),
		);

		// Query Loop Template Fields (shown when hasLoop is enabled).
		$this->controls['queryLoopSeparator'] = array(
			'tab'      => 'content',
			'group'    => 'hotspots',
			'type'     => 'separator',
			'label'    => esc_html__( 'Hotspots', 'bricksextras' ),
			'required' => array( 'hasLoop', '!=', '' ),
		);

		$this->controls['hotspotPitch'] = array(
			'tab'         => 'content',
			'group'       => 'hotspots',
			'label'       => 'Pitch',
			'inline'      => true,
			'type'        => 'text',
			'placeholder' => '0',
			'description' => esc_html__( 'Position', 'bricks' ) . ' (°) (' . esc_html__( 'Vertical', 'bricks' ) . ')',
			'required'    => array( 'hasLoop', '!=', '' ),
		);

		$this->controls['hotspotYaw'] = array(
			'tab'         => 'content',
			'group'       => 'hotspots',
			'inline'      => true,
			'label'       => 'Yaw',
			'type'        => 'text',
			'placeholder' => '0',
			'description' => esc_html__( 'Position', 'bricks' ) . ' (°) (' . esc_html__( 'Horizontal', 'bricks' ) . ')',
			'required'    => array( 'hasLoop', '!=', '' ),
		);

		$this->controls['icon'] = array(
			'tab'      => 'content',
			'group'    => 'hotspots',
			'label'    => esc_html__( 'Icon', 'bricks' ),
			'type'     => 'icon',
			'required' => array( 'hasLoop', '!=', '' ),
		);

		$this->controls['hotspotText'] = array(
			'tab'      => 'content',
			'group'    => 'hotspots',
			'label'    => esc_html__( 'Content', 'bricks' ) . ' (' . esc_html__( 'Tooltip', 'bricks' ) . ')',
			'type'     => 'editor',
			'required' => array( 'hasLoop', '!=', '' ),
		);

		$this->controls['buttonText'] = array(
			'tab'      => 'content',
			'group'    => 'hotspots',
			'label'    => esc_html__( 'Button text', 'bricks' ),
			'type'     => 'text',
			'inline'   => true,
			'required' => array( 'hasLoop', '!=', '' ),
		);

		$this->controls['hotspotType'] = array(
			'tab'         => 'content',
			'group'       => 'hotspots',
			'label'       => esc_html__( 'Type', 'bricks' ),
			'type'        => 'text',
			'inline'      => true,
			'placeholder' => 'info',
			'info'        => 'info | scene_link | link',
			'required'    => array( 'hasLoop', '!=', '' ),
		);

		$this->controls['hotspotLink'] = array(
			'tab'      => 'content',
			'group'    => 'hotspots',
			'label'    => esc_html__( 'Link URL  (used when type is "link")', 'bricksextras' ),
			'type'     => 'text',
			'inline'   => true,
			'required' => array( 'hasLoop', '!=', '' ),
		);

		$this->controls['hotspotSceneId'] = array(
			'tab'      => 'content',
			'group'    => 'hotspots',
			'label'    => esc_html__( 'Scene identifier', 'bricksextras' ),
			'type'     => 'text',
			'inline'   => true,
			'required' => array( 'hasLoop', '!=', '' ),
		);

		$this->controls['hotspotName'] = array(
			'tab'         => 'content',
			'group'       => 'hotspots',
			'label'       => esc_html__( 'Hotspot name', 'bricksextras' ),
			'type'        => 'text',
			'inline'      => true,
			'description' => esc_html__( 'Unique name to link to this hotspot from tooltip content using #hotspot-name', 'bricksextras' ),
			'required'    => array( 'hasLoop', '!=', '' ),
		);

		$this->controls['hotspotAriaLabel'] = array(
			'tab'      => 'content',
			'group'    => 'hotspots',
			'label'    => esc_html__( 'Aria label', 'bricksextras' ),
			'type'     => 'text',
			'inline'   => true,
			'required' => array( 'hasLoop', '!=', '' ),
		);

		$this->controls['viewerSceneSettingsSeparator'] = array(
			'tab'         => 'content',
			'group'       => 'viewer',
			'type'        => 'separator',
			'label'       => esc_html__( 'Scene Configuration', 'bricksextras' ),
			'description' => esc_html__( 'Initial conditions when user arrives at this scene. Leave black to use global settings.', 'bricksextras' ),
		);

		$this->controls['pitch'] = array(
			'tab'         => 'content',
			'group'       => 'viewer',
			'label'       => 'Pitch (' . esc_html__( 'Initial', 'bricks' ) . ')',
			'type'        => 'text',
			'inline'      => true,
			'units'       => false,
			'description' => esc_html__( 'Vertical', 'bricks' ) . ' (°)',
		);

		$this->controls['yaw'] = array(
			'tab'         => 'content',
			'group'       => 'viewer',
			'label'       => 'Yaw (' . esc_html__( 'Initial', 'bricks' ) . ')',
			'type'        => 'text',
			'inline'      => true,
			'units'       => false,
			'description' => esc_html__( 'Horizontal', 'bricks' ) . ' (°)',
		);

		$this->controls['hfov'] = array(
			'tab'    => 'content',
			'group'  => 'viewer',
			'label'  => esc_html__( 'Field of view', 'bricksextras' ),
			'type'   => 'text',
			'inline' => true,
			'units'  => false,
		);

		$this->controls['autoRotate'] = array(
			'tab'         => 'content',
			'group'       => 'viewer',
			'label'       => esc_html__( 'Auto rotate speed', 'bricksextras' ),
			'type'        => 'text',
			'inline'      => true,
			'units'       => false,
			'description' => esc_html__( 'Rotation speed in degrees per second (0 = disabled)', 'bricksextras' ),
		);
	}


	/**
	 * Enqueue scripts.
	 */
	public function enqueue_scripts() {

		if ( bricks_is_builder_main() ) {
			return;
		}

		// Enqueue our custom script.
		wp_enqueue_script( 'x-panoramaviewer', BRICKSEXTRAS_URL . 'components/assets/js/' . \BricksExtras\Helpers::maybe_minify_scripts( 'panoramaviewer' ) . '.js', array( 'bricks-scripts' ), \BricksExtras\Plugin::VERSION, true );

		if ( ! \BricksExtras\Helpers::element_css_added( $this->name ) ) {
			wp_enqueue_style( 'x-panoramaviewer', BRICKSEXTRAS_URL . 'components/assets/css/panoramaviewer.css', array(), \BricksExtras\Plugin::VERSION );
		}
	}

	/**
	 * Render element output.
	 */
	public function render() {

		$settings = $this->settings;

		// Get panorama image using helper function (force original image for panoramas).
		$panorama_image = \BricksExtras\Helpers::get_normalized_image_settings( $settings, 'panoramaImage', true );

		// On frontend, return early if no image.
		if ( ( empty( $panorama_image ) || empty( $panorama_image['url'] ) ) && ! \BricksExtras\Helpers::maybe_preview() ) {
			return $this->render_element_placeholder(
				array(
					'title' => esc_html__( 'No panorama image selected', 'bricksextras' ),
				)
			);
		}

		$panorama_url = ! empty( $panorama_image['url'] ) ? esc_url( bricks_render_dynamic_data( $panorama_image['url'] ) ) : '';

		$config = array(
			'type'        => 'equirectangular',
			'panorama'    => $panorama_url,
			'autoLoad'    => true,
			'crossOrigin' => 'anonymous',
		);

		// Add scene ID if set (for tours).
		if ( ! empty( $settings['sceneId'] ) ) {
			$config['sceneId'] = sanitize_key( bricks_render_dynamic_data( $settings['sceneId'] ) );
		}

		if ( ! empty( $settings['sceneTitle'] ) ) {
			$config['title'] = wp_kses_post( bricks_render_dynamic_data( $settings['sceneTitle'] ) );
		}

		// Optional settings - inherit from viewer if not set on scene.
		if ( isset( $settings['autoRotate'] ) && '' !== $settings['autoRotate'] ) {
			$config['autoRotate'] = floatval( $settings['autoRotate'] );
		}

		// Yaw - use scene setting or inherit from viewer.
		if ( isset( $settings['yaw'] ) && '' !== $settings['yaw'] ) {
			$config['yaw'] = floatval( $settings['yaw'] );
		}

		// Pitch - use scene setting or inherit from viewer.
		if ( isset( $settings['pitch'] ) && '' !== $settings['pitch'] ) {
			$config['pitch'] = floatval( $settings['pitch'] );
		}

		if ( isset( $settings['hfov'] ) && '' !== $settings['hfov'] ) {
			$config['hfov'] = floatval( $settings['hfov'] );
		}

		// Generate and set a unique identifier for this instance.
		$indentifier = \BricksExtras\Helpers::set_identifier_attribute( $this );

		// Set element attributes.
		$this->set_attribute( '_root', 'data-panorama-config', htmlspecialchars( wp_json_encode( $config, JSON_HEX_APOS | JSON_HEX_QUOT ), ENT_QUOTES, 'UTF-8' ) );

		$output = '';

		$output .= "<div {$this->render_attributes( '_root' )}>";

		if ( method_exists( '\Bricks\Frontend', 'render_children' ) ) {
			$output .= \Bricks\Frontend::render_children( $this );
		}

		// Render hotspots as DOM elements.
		$output .= $this->render_hotspots_dom( $settings );

		$output .= '</div>';

		echo $output;
	}

	/**
	 * Render hotspots as DOM elements
	 *
	 * @param array $settings Element settings.
	 */
	private function render_hotspots_dom( $settings ) {
		$hotspots_setting = empty( $settings['hotSpots'] ) ? false : $settings['hotSpots'];
		$has_query_loop   = isset( $settings['hasLoop'] );

		// Only render container if we have hotspots.
		if ( ! $hotspots_setting && ! $has_query_loop ) {
			return '';
		}

		$hotspots_output = '';

		$hotspots_output .= '<div class="x-hotspot-data" style="display: none;">';

		// Render query loop hotspots (takes priority over manual hotspots).
		if ( $has_query_loop ) {
			$query = new \Bricks\Query(
				array(
					'id'       => $this->id,
					'settings' => $settings,
				)
			);

			// Use Bricks query render method with callback.
			$hotspots_output .= $query->render( array( $this, 'render_hotspot_item' ), array() );

			$query->destroy();
			unset( $query );
		} elseif ( $hotspots_setting ) {
			// Render manual hotspots from repeater (only when query loop is NOT enabled).
			foreach ( $hotspots_setting as $hotspot_data ) {
				$hotspots_output .= $this->render_manual_hotspot( $hotspot_data );
			}
		}

		$hotspots_output .= '</div>';

		return $hotspots_output;
	}

	/**
	 * Render a single manual hotspot as DOM element
	 *
	 * @param array $hotspot_data Hotspot configuration data.
	 */
	private function render_manual_hotspot( $hotspot_data ) {
		// Default yaw and pitch to 0 if not provided.
		$pitch = isset( $hotspot_data['pitch'] ) && '' !== $hotspot_data['pitch'] ? floatval( bricks_render_dynamic_data( $hotspot_data['pitch'] ) ) : 0;
		$yaw   = isset( $hotspot_data['yaw'] ) && '' !== $hotspot_data['yaw'] ? floatval( bricks_render_dynamic_data( $hotspot_data['yaw'] ) ) : 0;
		$type  = isset( $hotspot_data['type'] ) ? sanitize_key( $hotspot_data['type'] ) : 'info';

		$attributes = array(
			'class'      => 'x-hotspot-item',
			'data-pitch' => $pitch,
			'data-yaw'   => $yaw,
			'data-type'  => $type,
		);

		if ( ! empty( $hotspot_data['hotspotName'] ) ) {
			$attributes['data-hotspot-id'] = sanitize_key( bricks_render_dynamic_data( $hotspot_data['hotspotName'] ) );
		}

		if ( ! empty( $hotspot_data['hotspotAriaLabel'] ) ) {
			$attributes['data-aria-label'] = esc_attr( bricks_render_dynamic_data( $hotspot_data['hotspotAriaLabel'] ) );
		}

		// Add type-specific attributes.
		if ( 'link' === $type && ! empty( $hotspot_data['link'] ) ) {
			$temp_key = '_hotspot_link_temp';
			$this->set_link_attributes( $temp_key, $hotspot_data['link'] );
			$resolved = isset( $this->attributes[ $temp_key ] ) ? $this->attributes[ $temp_key ] : array();
			unset( $this->attributes[ $temp_key ] );
			// Flatten arrays to strings and store all resolved attributes as JSON.
			$flattened = array();
			foreach ( $resolved as $attr_name => $attr_val ) {
				$flattened[ $attr_name ] = is_array( $attr_val ) ? implode( ' ', $attr_val ) : $attr_val;
			}
			if ( ! empty( $flattened['href'] ) ) {
				$attributes['data-link'] = esc_url( $flattened['href'] );
			}
			if ( ! empty( $flattened ) ) {
				$attributes['data-link-attrs'] = wp_json_encode( $flattened );
			}
		} elseif ( 'scene' === $type && ! empty( $hotspot_data['sceneId'] ) ) {
			$attributes['data-scene-id'] = sanitize_key( bricks_render_dynamic_data( $hotspot_data['sceneId'] ) );
		}

		$hotspot_output = '';

		// Build attributes string.
		$hotspot_output .= '<div';
		foreach ( $attributes as $key => $value ) {
			$hotspot_output .= ' ' . esc_attr( $key ) . '="' . esc_attr( $value ) . '"';
		}
		$hotspot_output .= '>';

		// Render icon.
		if ( ! empty( $hotspot_data['icon'] ) ) {
			// Render dynamic data first to check if it has actual content.
			$icon_html = self::render_icon( $hotspot_data['icon'] );
			// Check if icon has meaningful content (not just base classes like "dashicons ").
			if ( ! empty( $icon_html ) && ! preg_match( '/class="[^"]*dashicons\s+"/', $icon_html ) ) {
				$hotspot_output .= '<div class="x-hotspot-icon">';
				$hotspot_output .= $icon_html;
				$hotspot_output .= '</div>';
			}
		}

		// Render button text and tooltip text content.
		foreach ( array(
			'buttonText' => 'x-hotspot-button-text',
			'text'       => 'x-hotspot-text',
		) as $key => $class ) {
			if ( ! empty( $hotspot_data[ $key ] ) ) {
				$hotspot_output .= '<div class="' . $class . '">';
				$hotspot_output .= wp_kses_post( bricks_render_dynamic_data( $hotspot_data[ $key ] ) );
				$hotspot_output .= '</div>';
			}
		}

		$hotspot_output .= '</div>';

		return $hotspot_output;
	}

	/**
	 * Render callback for query loop hotspots.
	 */
	public function render_hotspot_item() {
		$settings = $this->settings;

		// Get dynamic data for coordinates.
		$pitch = isset( $settings['hotspotPitch'] ) ? intval( bricks_render_dynamic_data( $settings['hotspotPitch'] ) ) : 0;
		$yaw   = isset( $settings['hotspotYaw'] ) ? intval( bricks_render_dynamic_data( $settings['hotspotYaw'] ) ) : 0;
		$type  = isset( $settings['hotspotType'] ) ? bricks_render_dynamic_data( $settings['hotspotType'] ) : 'info';

		// Validate coordinates.
		if ( '' === $pitch && '' === $yaw ) {
			return '';
		}

		$attributes = array(
			'class'      => 'x-hotspot-item',
			'data-pitch' => $pitch,
			'data-yaw'   => $yaw,
			'data-type'  => sanitize_key( $type ),
		);

		if ( isset( $settings['hotspotName'] ) ) {
			$hotspot_name = sanitize_key( bricks_render_dynamic_data( $settings['hotspotName'] ) );
			if ( $hotspot_name ) {
				$attributes['data-hotspot-id'] = $hotspot_name;
			}
		}

		if ( isset( $settings['hotspotAriaLabel'] ) ) {
			$aria_label = esc_attr( bricks_render_dynamic_data( $settings['hotspotAriaLabel'] ) );
			if ( $aria_label ) {
				$attributes['data-aria-label'] = $aria_label;
			}
		}

		// Add type-specific attributes.
		if ( 'link' === $type && ! empty( $settings['hotspotLink'] ) ) {
			$temp_key = '_hotspot_link_temp';
			$this->set_link_attributes( $temp_key, $settings['hotspotLink'] );
			$resolved = isset( $this->attributes[ $temp_key ] ) ? $this->attributes[ $temp_key ] : array();
			unset( $this->attributes[ $temp_key ] );
			// Flatten arrays to strings and store all resolved attributes as JSON.
			$flattened = array();
			foreach ( $resolved as $attr_name => $attr_val ) {
				$flattened[ $attr_name ] = is_array( $attr_val ) ? implode( ' ', $attr_val ) : $attr_val;
			}
			if ( ! empty( $flattened['href'] ) ) {
				$attributes['data-link'] = esc_url( $flattened['href'] );
			}
			if ( ! empty( $flattened ) ) {
				$attributes['data-link-attrs'] = wp_json_encode( $flattened );
			}
		} elseif ( 'scene' === $type && isset( $settings['hotspotSceneId'] ) ) {
			$scene_id = bricks_render_dynamic_data( $settings['hotspotSceneId'] );
			if ( $scene_id ) {
				$attributes['data-scene-id'] = sanitize_key( $scene_id );
			}
		}

		$hotspot_output = '';

		// Build attributes string.
		$hotspot_output .= '<div';
		foreach ( $attributes as $key => $value ) {
			$hotspot_output .= ' ' . esc_attr( $key ) . '="' . esc_attr( $value ) . '"';
		}
		$hotspot_output .= '>';

		// Render icon.
		if ( isset( $settings['icon'] ) && ! empty( $settings['icon'] ) ) {
			// Render dynamic data first to check if it has actual content.
			$icon_html = self::render_icon( $settings['icon'] );

			// Check if icon has meaningful content (not just base classes like "dashicons ").
			if ( ! empty( $icon_html ) && ! preg_match( '/class="[^"]*dashicons\s+"/', $icon_html ) ) {
				// Icon has specific icon class, not just base class.
				$hotspot_output .= '<div class="x-hotspot-icon">';
				$hotspot_output .= $icon_html;
				$hotspot_output .= '</div>';
			}
		}

		// Render button text (if set).
		if ( isset( $settings['buttonText'] ) ) {
			$button_text = bricks_render_dynamic_data( $settings['buttonText'] );
			if ( $button_text ) {
				$hotspot_output .= '<div class="x-hotspot-button-text">' . wp_kses_post( $button_text ) . '</div>';
			}
		}

		// Render text content.
		if ( isset( $settings['hotspotText'] ) ) {
			$content = $this->settings['hotspotText'];
			$content = $this->render_dynamic_data( $content );
			$content = \Bricks\Helpers::parse_editor_content( $content );
			if ( $content ) {
				$hotspot_output .= '<div class="x-hotspot-text">' . wp_kses_post( $content ) . '</div>';
			}
		}

		$hotspot_output .= '</div>';

		return $hotspot_output;
	}
}
