<?php
/**
 * Widget Name: Image Hotspot
 * Description: An image with positioned hotspot markers — each marker opens a
 *              tooltip with a title, text and an optional link. Markers are
 *              real buttons with ARIA wiring, open on hover or click, and the
 *              tooltip side is selectable per hotspot so nothing overflows the
 *              image edges. Ships with selectable visual styles. Only the
 *              selected style CSS file is loaded on the frontend.
 *
 * @package    captain-widgets-kit
 * @subpackage captain-widgets-kit/includes
 * @since      1.7.0
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

use Elementor\Widget_Base;
use Elementor\Controls_Manager;
use Elementor\Repeater;
use Elementor\Group_Control_Typography;
use Elementor\Control_Media;
use Elementor\Icons_Manager;
use Elementor\Utils;

/**
 * Class Captwiki_Image_Hotspot
 *
 * @since 1.7.0
 */
class Captwiki_Image_Hotspot extends Widget_Base {

	/**
	 * Get widget name.
	 *
	 * @since 1.7.0
	 * @return string
	 */
	public function get_name(): string {
		return 'captwiki-image-hotspot';
	}

	/**
	 * Get widget title.
	 *
	 * @since 1.7.0
	 * @return string
	 */
	public function get_title(): string {
		return esc_html__( 'Image Hotspot', 'captain-widgets-kit' );
	}

	/**
	 * Get widget icon.
	 *
	 * @since 1.7.0
	 * @return string
	 */
	public function get_icon(): string {
		return 'eicon-image-hotspot captwiki-el-logo';
	}

	/**
	 * Get widget categories.
	 *
	 * @since 1.7.0
	 * @return array
	 */
	public function get_categories(): array {
		return array( 'captwiki-essential' );
	}

	/**
	 * Get widget keywords.
	 *
	 * @since 1.7.0
	 * @return array
	 */
	public function get_keywords(): array {
		return array( 'hotspot', 'image', 'pin', 'marker', 'tooltip', 'pointer', 'captain-widgets-kit' );
	}

	/**
	 * Frontend script dependency.
	 *
	 * @since 1.7.0
	 * @return array
	 */
	public function get_script_depends(): array {
		return array( 'captwiki-image-hotspot' );
	}

	/**
	 * Common stylesheet dependency.
	 *
	 * @since 1.7.0
	 * @return array
	 */
	public function get_style_depends(): array {
		return array( 'captwiki_image_hotspot' );
	}

	/**
	 * Disable Elementor's default inner wrapper.
	 *
	 * @since 1.7.0
	 * @return bool
	 */
	public function has_widget_inner_wrapper(): bool {
		return ! \Elementor\Plugin::$instance->experiments->is_feature_active( 'e_optimized_markup' );
	}

	/**
	 * Selectable visual styles.
	 *
	 * @since 1.7.0
	 * @return array
	 */
	private function captwiki_style_options(): array {
		return array(
			'style-1' => esc_html__( 'Style 1 – Pulse Dot', 'captain-widgets-kit' ),
			'style-2' => esc_html__( 'Style 2 – Numbered Circles', 'captain-widgets-kit' ),
			'style-3' => esc_html__( 'Style 3 – Map Pin', 'captain-widgets-kit' ),
			'style-4' => esc_html__( 'Style 4 – Frosted Glass', 'captain-widgets-kit' ),
			'style-5' => esc_html__( 'Style 5 – Plus Toggle', 'captain-widgets-kit' ),
		);
	}

	/**
	 * Register widget controls.
	 *
	 * @since 1.7.0
	 * @return void
	 */
	protected function register_controls(): void {
		$this->register_image_controls();
		$this->register_hotspots_controls();
		$this->register_settings_controls();

		$this->register_layout_style_controls();
		$this->register_marker_style_controls();
		$this->register_tooltip_style_controls();
	}

	/**
	 * Content tab — base image.
	 *
	 * @since 1.7.0
	 * @return void
	 */
	private function register_image_controls(): void {

		$this->start_controls_section(
			'section_image',
			array(
				'label' => esc_html__( 'Image', 'captain-widgets-kit' ),
				'tab'   => Controls_Manager::TAB_CONTENT,
			)
		);

		$this->add_control(
			'widget_style',
			array(
				'label'   => esc_html__( 'Style', 'captain-widgets-kit' ),
				'type'    => Controls_Manager::SELECT,
				'default' => 'style-1',
				'options' => $this->captwiki_style_options(),
			)
		);

		$this->add_control(
			'image',
			array(
				'label'   => esc_html__( 'Image', 'captain-widgets-kit' ),
				'type'    => Controls_Manager::MEDIA,
				'default' => array( 'url' => Utils::get_placeholder_image_src() ),
				'dynamic' => array( 'active' => true ),
			)
		);

		$this->end_controls_section();
	}

	/**
	 * Content tab — hotspots repeater.
	 *
	 * @since 1.7.0
	 * @return void
	 */
	private function register_hotspots_controls(): void {

		$this->start_controls_section(
			'section_hotspots',
			array(
				'label' => esc_html__( 'Hotspots', 'captain-widgets-kit' ),
				'tab'   => Controls_Manager::TAB_CONTENT,
			)
		);

		$repeater = new Repeater();

		$repeater->add_control(
			'spot_title',
			array(
				'label'       => esc_html__( 'Title', 'captain-widgets-kit' ),
				'type'        => Controls_Manager::TEXT,
				'default'     => esc_html__( 'Hotspot', 'captain-widgets-kit' ),
				'label_block' => true,
				'dynamic'     => array( 'active' => true ),
			)
		);

		$repeater->add_control(
			'spot_text',
			array(
				'label'   => esc_html__( 'Text', 'captain-widgets-kit' ),
				'type'    => Controls_Manager::TEXTAREA,
				'rows'    => 3,
				'default' => esc_html__( 'Add a short description for this point of interest.', 'captain-widgets-kit' ),
				'dynamic' => array( 'active' => true ),
			)
		);

		$repeater->add_control(
			'spot_link',
			array(
				'label'   => esc_html__( 'Link (optional)', 'captain-widgets-kit' ),
				'type'    => Controls_Manager::URL,
				'dynamic' => array( 'active' => true ),
				'default' => array( 'url' => '' ),
			)
		);

		$repeater->add_control(
			'spot_link_text',
			array(
				'label'   => esc_html__( 'Link Text', 'captain-widgets-kit' ),
				'type'    => Controls_Manager::TEXT,
				'default' => esc_html__( 'Learn more', 'captain-widgets-kit' ),
			)
		);

		$repeater->add_control(
			'spot_icon',
			array(
				'label'       => esc_html__( 'Icon (optional)', 'captain-widgets-kit' ),
				'type'        => Controls_Manager::ICONS,
				'skin'        => 'inline',
				'label_block' => false,
				'description' => esc_html__( 'Leave empty to show the hotspot number.', 'captain-widgets-kit' ),
			)
		);

		$repeater->add_responsive_control(
			'pos_x',
			array(
				'label'     => esc_html__( 'Horizontal Position (%)', 'captain-widgets-kit' ),
				'type'      => Controls_Manager::SLIDER,
				'range'     => array(
					'px' => array(
						'min' => 0,
						'max' => 100,
					),
				),
				'default'   => array( 'size' => 50 ),
				'selectors' => array(
					'{{WRAPPER}} {{CURRENT_ITEM}}' => 'left: {{SIZE}}%;',
				),
			)
		);

		$repeater->add_responsive_control(
			'pos_y',
			array(
				'label'     => esc_html__( 'Vertical Position (%)', 'captain-widgets-kit' ),
				'type'      => Controls_Manager::SLIDER,
				'range'     => array(
					'px' => array(
						'min' => 0,
						'max' => 100,
					),
				),
				'default'   => array( 'size' => 50 ),
				'selectors' => array(
					'{{WRAPPER}} {{CURRENT_ITEM}}' => 'top: {{SIZE}}%;',
				),
			)
		);

		$repeater->add_control(
			'tooltip_side',
			array(
				'label'   => esc_html__( 'Tooltip Side', 'captain-widgets-kit' ),
				'type'    => Controls_Manager::SELECT,
				'default' => 'top',
				'options' => array(
					'top'    => esc_html__( 'Top', 'captain-widgets-kit' ),
					'bottom' => esc_html__( 'Bottom', 'captain-widgets-kit' ),
					'left'   => esc_html__( 'Left', 'captain-widgets-kit' ),
					'right'  => esc_html__( 'Right', 'captain-widgets-kit' ),
				),
			)
		);

		$this->add_control(
			'hotspots',
			array(
				'label'       => esc_html__( 'Hotspots', 'captain-widgets-kit' ),
				'type'        => Controls_Manager::REPEATER,
				'fields'      => $repeater->get_controls(),
				'default'     => array(
					array(
						'spot_title' => esc_html__( 'First Feature', 'captain-widgets-kit' ),
						'pos_x'      => array( 'size' => 30 ),
						'pos_y'      => array( 'size' => 35 ),
					),
					array(
						'spot_title' => esc_html__( 'Second Feature', 'captain-widgets-kit' ),
						'pos_x'      => array( 'size' => 65 ),
						'pos_y'      => array( 'size' => 60 ),
					),
				),
				'title_field' => '{{{ spot_title }}}',
			)
		);

		$this->end_controls_section();
	}

	/**
	 * Content tab — behaviour settings.
	 *
	 * @since 1.7.0
	 * @return void
	 */
	private function register_settings_controls(): void {

		$this->start_controls_section(
			'section_settings',
			array(
				'label' => esc_html__( 'Settings', 'captain-widgets-kit' ),
				'tab'   => Controls_Manager::TAB_CONTENT,
			)
		);

		$this->add_control(
			'tooltip_trigger',
			array(
				'label'   => esc_html__( 'Open Tooltip On', 'captain-widgets-kit' ),
				'type'    => Controls_Manager::SELECT,
				'default' => 'hover',
				'options' => array(
					'hover' => esc_html__( 'Hover', 'captain-widgets-kit' ),
					'click' => esc_html__( 'Click', 'captain-widgets-kit' ),
				),
			)
		);

		$this->add_control(
			'pulse_animation',
			array(
				'label'        => esc_html__( 'Pulse Animation', 'captain-widgets-kit' ),
				'type'         => Controls_Manager::SWITCHER,
				'label_on'     => esc_html__( 'Yes', 'captain-widgets-kit' ),
				'label_off'    => esc_html__( 'No', 'captain-widgets-kit' ),
				'return_value' => 'yes',
				'default'      => 'yes',
			)
		);

		$this->end_controls_section();
	}

	/**
	 * Style tab — layout ( width / alignment ).
	 *
	 * @since 1.7.0
	 * @return void
	 */
	private function register_layout_style_controls(): void {

		$this->start_controls_section(
			'section_layout_style',
			array(
				'label' => esc_html__( 'Layout', 'captain-widgets-kit' ),
				'tab'   => Controls_Manager::TAB_STYLE,
			)
		);

		$this->add_responsive_control(
			'box_width',
			array(
				'label'      => esc_html__( 'Width', 'captain-widgets-kit' ),
				'type'       => Controls_Manager::SLIDER,
				'size_units' => array( 'px', '%' ),
				'range'      => array(
					'px' => array(
						'min' => 120,
						'max' => 1400,
					),
					'%'  => array(
						'min' => 10,
						'max' => 100,
					),
				),
				'selectors'  => array(
					'{{WRAPPER}} .captwiki-hotspot' => 'max-width: {{SIZE}}{{UNIT}};',
				),
			)
		);

		$this->add_responsive_control(
			'box_align',
			array(
				'label'                => esc_html__( 'Alignment', 'captain-widgets-kit' ),
				'type'                 => Controls_Manager::CHOOSE,
				'default'              => 'center',
				'options'              => array(
					'left'   => array(
						'title' => esc_html__( 'Left', 'captain-widgets-kit' ),
						'icon'  => 'eicon-text-align-left',
					),
					'center' => array(
						'title' => esc_html__( 'Center', 'captain-widgets-kit' ),
						'icon'  => 'eicon-text-align-center',
					),
					'right'  => array(
						'title' => esc_html__( 'Right', 'captain-widgets-kit' ),
						'icon'  => 'eicon-text-align-right',
					),
				),
				'selectors_dictionary' => array(
					'left'   => 'margin-left: 0; margin-right: auto;',
					'center' => 'margin-left: auto; margin-right: auto;',
					'right'  => 'margin-left: auto; margin-right: 0;',
				),
				'selectors'            => array(
					'{{WRAPPER}} .captwiki-hotspot' => '{{VALUE}}',
				),
			)
		);

		$this->add_responsive_control(
			'box_border_radius',
			array(
				'label'      => esc_html__( 'Border Radius', 'captain-widgets-kit' ),
				'type'       => Controls_Manager::DIMENSIONS,
				'size_units' => array( 'px', '%' ),
				'selectors'  => array(
					'{{WRAPPER}} .captwiki-hotspot__img' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
				),
			)
		);

		$this->end_controls_section();
	}

	/**
	 * Style tab — markers.
	 *
	 * @since 1.7.0
	 * @return void
	 */
	private function register_marker_style_controls(): void {

		$this->start_controls_section(
			'section_marker_style',
			array(
				'label' => esc_html__( 'Marker', 'captain-widgets-kit' ),
				'tab'   => Controls_Manager::TAB_STYLE,
			)
		);

		$this->add_control(
			'marker_accent_color',
			array(
				'label'     => esc_html__( 'Accent Color', 'captain-widgets-kit' ),
				'type'      => Controls_Manager::COLOR,
				'default'   => '',
				'selectors' => array(
					'{{WRAPPER}} .captwiki-hotspot' => '--captwiki-hs-accent: {{VALUE}};',
				),
			)
		);

		$this->add_control(
			'marker_color',
			array(
				'label'     => esc_html__( 'Icon / Number Color', 'captain-widgets-kit' ),
				'type'      => Controls_Manager::COLOR,
				'default'   => '',
				'selectors' => array(
					'{{WRAPPER}} .captwiki-hotspot' => '--captwiki-hs-marker-color: {{VALUE}};',
				),
			)
		);

		$this->add_responsive_control(
			'marker_size',
			array(
				'label'      => esc_html__( 'Size', 'captain-widgets-kit' ),
				'type'       => Controls_Manager::SLIDER,
				'size_units' => array( 'px' ),
				'range'      => array(
					'px' => array(
						'min' => 16,
						'max' => 72,
					),
				),
				'selectors'  => array(
					'{{WRAPPER}} .captwiki-hotspot' => '--captwiki-hs-marker: {{SIZE}}{{UNIT}};',
				),
			)
		);

		$this->end_controls_section();
	}

	/**
	 * Style tab — tooltip.
	 *
	 * @since 1.7.0
	 * @return void
	 */
	private function register_tooltip_style_controls(): void {

		$this->start_controls_section(
			'section_tooltip_style',
			array(
				'label' => esc_html__( 'Tooltip', 'captain-widgets-kit' ),
				'tab'   => Controls_Manager::TAB_STYLE,
			)
		);

		$this->add_responsive_control(
			'tooltip_width',
			array(
				'label'      => esc_html__( 'Width', 'captain-widgets-kit' ),
				'type'       => Controls_Manager::SLIDER,
				'size_units' => array( 'px' ),
				'range'      => array(
					'px' => array(
						'min' => 120,
						'max' => 360,
					),
				),
				'selectors'  => array(
					'{{WRAPPER}} .captwiki-hotspot' => '--captwiki-hs-tooltip-w: {{SIZE}}{{UNIT}};',
				),
			)
		);

		$this->add_control(
			'tooltip_bg_color',
			array(
				'label'     => esc_html__( 'Background Color', 'captain-widgets-kit' ),
				'type'      => Controls_Manager::COLOR,
				'default'   => '',
				'selectors' => array(
					'{{WRAPPER}} .captwiki-hotspot' => '--captwiki-hs-tooltip-bg: {{VALUE}};',
				),
			)
		);

		$this->add_control(
			'tooltip_title_color',
			array(
				'label'     => esc_html__( 'Title Color', 'captain-widgets-kit' ),
				'type'      => Controls_Manager::COLOR,
				'default'   => '',
				'selectors' => array(
					'{{WRAPPER}} .captwiki-hotspot__title' => 'color: {{VALUE}};',
				),
			)
		);

		$this->add_group_control(
			Group_Control_Typography::get_type(),
			array(
				'name'     => 'tooltip_title_typography',
				'label'    => esc_html__( 'Title Typography', 'captain-widgets-kit' ),
				'selector' => '{{WRAPPER}} .captwiki-hotspot__title',
			)
		);

		$this->add_control(
			'tooltip_text_color',
			array(
				'label'     => esc_html__( 'Text Color', 'captain-widgets-kit' ),
				'type'      => Controls_Manager::COLOR,
				'default'   => '',
				'selectors' => array(
					'{{WRAPPER}} .captwiki-hotspot__text' => 'color: {{VALUE}};',
				),
			)
		);

		$this->add_group_control(
			Group_Control_Typography::get_type(),
			array(
				'name'     => 'tooltip_text_typography',
				'label'    => esc_html__( 'Text Typography', 'captain-widgets-kit' ),
				'selector' => '{{WRAPPER}} .captwiki-hotspot__text',
			)
		);

		$this->end_controls_section();
	}

	/**
	 * Capture an Elementor icon as an HTML string.
	 *
	 * @since 1.7.0
	 * @param array $icon Icon control value.
	 * @return string
	 */
	private function captwiki_get_icon_html( array $icon ): string {
		ob_start();
		Icons_Manager::render_icon( $icon, array( 'aria-hidden' => 'true' ) );
		return (string) ob_get_clean();
	}

	/**
	 * Render one hotspot ( marker + tooltip ).
	 *
	 * @since 1.7.0
	 * @param array $spot   Repeater item.
	 * @param int   $number 1-based hotspot number.
	 * @return void
	 */
	private function captwiki_render_hotspot( array $spot, int $number ): void {

		$title   = isset( $spot['spot_title'] ) ? trim( (string) $spot['spot_title'] ) : '';
		$text    = isset( $spot['spot_text'] ) ? trim( (string) $spot['spot_text'] ) : '';
		$icon    = isset( $spot['spot_icon'] ) ? (array) $spot['spot_icon'] : array();
		$side    = isset( $spot['tooltip_side'] ) && in_array( $spot['tooltip_side'], array( 'top', 'bottom', 'left', 'right' ), true ) ? $spot['tooltip_side'] : 'top';
		$item_id = ! empty( $spot['_id'] ) ? sanitize_html_class( $spot['_id'] ) : (string) $number;
		$tip_id  = 'captwiki-hs-tip-' . $this->get_id() . '-' . $item_id;

		echo '<div class="captwiki-hotspot__point elementor-repeater-item-' . esc_attr( $item_id ) . '">';

		printf(
			'<button type="button" class="captwiki-hotspot__marker" aria-expanded="false" aria-controls="%1$s" aria-label="%2$s">',
			esc_attr( $tip_id ),
			esc_attr( '' !== $title ? $title : esc_html__( 'Hotspot', 'captain-widgets-kit' ) )
		);

		if ( ! empty( $icon['value'] ) ) {
			echo '<span class="captwiki-hotspot__marker-icon" aria-hidden="true">' . $this->captwiki_get_icon_html( $icon ) . '</span>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
		} else {
			echo '<span class="captwiki-hotspot__num" aria-hidden="true">' . esc_html( (string) $number ) . '</span>';
		}

		echo '</button>';

		printf(
			'<div class="captwiki-hotspot__tooltip captwiki-hotspot__tooltip--%1$s" id="%2$s" role="tooltip">',
			esc_attr( $side ),
			esc_attr( $tip_id )
		);

		if ( '' !== $title ) {
			echo '<h4 class="captwiki-hotspot__title">' . esc_html( $title ) . '</h4>';
		}

		if ( '' !== $text ) {
			echo '<p class="captwiki-hotspot__text">' . esc_html( $text ) . '</p>';
		}

		$link_text = isset( $spot['spot_link_text'] ) ? trim( (string) $spot['spot_link_text'] ) : '';

		if ( ! empty( $spot['spot_link']['url'] ) && '' !== $link_text ) {
			$this->add_link_attributes( 'spot_link_' . $item_id, $spot['spot_link'] );
			$this->add_render_attribute( 'spot_link_' . $item_id, 'class', 'captwiki-hotspot__link' );

			echo '<a ' . $this->get_render_attribute_string( 'spot_link_' . $item_id ) . '>' . esc_html( $link_text ) . '</a>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
		}

		echo '</div>'; // tooltip.
		echo '</div>'; // point.
	}

	/**
	 * Render widget output on the frontend.
	 *
	 * @since 1.7.0
	 * @return void
	 */
	protected function render(): void {
		$settings = $this->get_settings_for_display();

		$image_url = ! empty( $settings['image']['url'] ) ? $settings['image']['url'] : '';

		if ( '' === $image_url || empty( $settings['hotspots'] ) || ! is_array( $settings['hotspots'] ) ) {
			return;
		}

		$allowed_styles = array_keys( $this->captwiki_style_options() );
		$style          = in_array( $settings['widget_style'], $allowed_styles, true ) ? $settings['widget_style'] : 'style-1';
		$trigger        = 'click' === $settings['tooltip_trigger'] ? 'click' : 'hover';
		$pulse          = 'yes' === $settings['pulse_animation'];

		$image_alt = ! empty( $settings['image']['id'] ) ? Control_Media::get_image_alt( $settings['image'] ) : '';

		// Load only the active style stylesheet, depending on the common one.
		wp_enqueue_style(
			'captwiki-image-hotspot-' . $style,
			CAPTWIKI_URL . 'assets/css/widgets/image-hotspot/captwiki-image-hotspot-' . $style . '.css',
			array( 'captwiki_image_hotspot' ),
			CAPTWIKI_VERSION
		);

		$classes = 'captwiki-hotspot captwiki-' . $style . ' captwiki-hotspot--' . $trigger;

		if ( $pulse ) {
			$classes .= ' captwiki-hotspot--pulse';
		}

		printf(
			'<div class="%1$s" data-trigger="%2$s">',
			esc_attr( $classes ),
			esc_attr( $trigger )
		);

		echo '<div class="captwiki-hotspot__frame">';

		printf(
			'<img class="captwiki-hotspot__img" src="%1$s" alt="%2$s" loading="lazy" />',
			esc_url( $image_url ),
			esc_attr( $image_alt )
		);

		$number = 1;
		foreach ( $settings['hotspots'] as $spot ) {
			$this->captwiki_render_hotspot( (array) $spot, $number );
			++$number;
		}

		echo '</div>'; // frame.
		echo '</div>'; // hotspot.
	}
}
