<?php

namespace PhotoSphereViewer\Includes;

class PhotoSphereViewerShortcode {

    private static $instance_count = 0;

    private function is_pro_activated(): bool {
        return ProStatus::is_active();
    }

    public function __construct() {
        add_shortcode('photo_sphere_viewer', array($this, 'render_shortcode'));
        add_shortcode('psv', array($this, 'render_shortcode'));
        add_shortcode('psv_tour', array($this, 'render_tour_shortcode'));
        add_shortcode('psv_video', array($this, 'render_video_shortcode'));
        add_shortcode('psv_ar', array($this, 'render_ar_shortcode'));
    }

    /**
     * =========================================================================
     * [psv] / [photo_sphere_viewer] — Basic panorama viewer (free + premium)
     * =========================================================================
     *
     * Gallery attrs:  gallery (JSON), gallery_visible, gallery_hide_on_click,
     *                 gallery_arrows, gallery_thumb_width, gallery_thumb_height
     *
     * Premium attrs:  compass, compass_size, gyroscope,
     *                 visible_range_yaw, visible_range_pitch
     */
    public function render_shortcode($atts, $content = null) {
        wp_enqueue_script('psv-main');
        wp_enqueue_style('psv-style');
        self::$instance_count++;

        $default = [
            'id'                     => '',
            'class'                  => '',
            'image'                  => PSV_ASSETS_URL . 'img/sphere.jpg',
            'caption'                => esc_html__('Photo Sphere Viewer', 'photo-sphere-viewer'),
            'navbar'                 => 'autorotate,download,caption,fullscreen',
            'width'                  => 100,
            'height'                 => 80,
            'min_fov'                => 30,
            'max_fov'                => 90,
            'default_zoom_lavel'     => 50,
            'default_yaw'            => 0,
            'default_pitch'          => 0,
            'default_longitude'      => null,
            'default_latitude'       => null,
            'longitude_range'        => 0,
            'latitude_range'         => 0,
            'autorotate_delay'       => '',
            'autorotate_speed'       => 10,
            'autorotate_autoplay'    => 'no',
            'fish_eye'               => 'no',
            'mouse_wheel'            => 'yes',
            'mousewheel_ctrl_key'    => 'no',
            'mouse_move'             => 'yes',
            'touch_move_two_fingers' => 'yes',
            'capture_cursor'         => 'no',
            'move_speed'             => 1,
            'mouse_wheel_speed'      => 1,
            'zoom_button_increment'  => 2,
            'canvas_background'      => '#333',
            // Gallery
            'gallery'                => '',
            'gallery_visible'        => 'yes',
            'gallery_hide_on_click'  => 'yes',
            'gallery_arrows'         => 'no',
            'gallery_thumb_width'    => 200,
            'gallery_thumb_height'   => 100,
            // Premium plugins
            'compass'                => 'no',
            'compass_size'           => 120,
            'gyroscope'              => 'no',
            'visible_range_yaw'      => '',
            'visible_range_pitch'    => '',
            // Image quality (default ON: load the original uploaded file when possible)
            'use_original'           => 'yes',
        ];

        $atts = shortcode_atts($default, $atts, 'photo_sphere_viewer');

        $use_original = ($atts['use_original'] !== 'no');

        // Backward compat
        if ($atts['default_longitude'] !== null && $atts['default_yaw'] == 0) {
            $atts['default_yaw'] = $atts['default_longitude'];
        }
        if ($atts['default_latitude'] !== null && $atts['default_pitch'] == 0) {
            $atts['default_pitch'] = $atts['default_latitude'];
        }

        $id             = wp_unique_id('xero-psv-container-');
        $navbar_options = array_map('trim', explode(',', $atts['navbar']));
        $autorotate     = ($atts['autorotate_delay'] !== '') ? $atts['autorotate_delay'] : false;
        $autorotate_speed = ($atts['autorotate_speed'] !== '') ? (float) ($atts['autorotate_speed'] / 100) : 0.2;

        // ── Gallery plugin ──
        $gallery_plugin = null;
        if (!empty($atts['gallery'])) {
            $gallery_items_raw = json_decode(wp_unslash($atts['gallery']), true);
            if (is_array($gallery_items_raw) && count($gallery_items_raw)) {
                $gallery_items = [];
                foreach ($gallery_items_raw as $i => $item) {
                    if (empty($item['panorama'])) continue;
                    $gallery_panorama_url = ImageResolver::resolve_url($item['panorama'], $use_original, 'gallery-item');
                    $gallery_items[] = [
                        'id'        => 'gallery-' . ($i + 1),
                        'name'      => $item['name'] ?? ('Panorama ' . ($i + 1)),
                        'panorama'  => $gallery_panorama_url,
                        'thumbnail' => $item['thumbnail'] ?? $gallery_panorama_url,
                    ];
                }
                if (!empty($gallery_items)) {
                    $navbar_options[] = 'gallery';
                    $gallery_plugin = [
                        'items'            => $gallery_items,
                        'visibleOnLoad'    => ('yes' === $atts['gallery_visible']),
                        'hideOnClick'      => ('yes' === $atts['gallery_hide_on_click']),
                        'navigationArrows' => ('yes' === $atts['gallery_arrows']),
                        'thumbnailSize'    => [
                            'width'  => (int) $atts['gallery_thumb_width'],
                            'height' => (int) $atts['gallery_thumb_height'],
                        ],
                    ];
                }
            }
        }

        // ── Premium plugins (only when pro is active) ──
        $compass_plugin = null;
        $gyroscope_plugin = null;
        $visible_range_plugin = null;

        if ($this->is_pro_activated()) {
            if ('yes' === $atts['compass']) {
                $compass_plugin = [
                    'size' => (int) $atts['compass_size'] . 'px',
                ];
            }
            if ('yes' === $atts['gyroscope']) {
                $gyroscope_plugin = true;
            }
            if (!empty($atts['visible_range_yaw']) || !empty($atts['visible_range_pitch'])) {
                $vr = [];
                if (!empty($atts['visible_range_yaw'])) {
                    $parts = array_map('trim', explode(',', $atts['visible_range_yaw']));
                    if (count($parts) === 2) {
                        $vr['horizontalRange'] = [$parts[0] . 'deg', $parts[1] . 'deg'];
                    }
                }
                if (!empty($atts['visible_range_pitch'])) {
                    $parts = array_map('trim', explode(',', $atts['visible_range_pitch']));
                    if (count($parts) === 2) {
                        $vr['verticalRange'] = [$parts[0] . 'deg', $parts[1] . 'deg'];
                    }
                }
                if (!empty($vr)) {
                    $visible_range_plugin = $vr;
                }
            }
        }

        $data = array_filter([
            'container'           => $id,
            'panorama'            => ImageResolver::resolve_url($atts['image'], $use_original, 'panorama'),
            'caption'             => [$atts['caption']],
            'navbar'              => $navbar_options,
            'size'                => [
                'width'  => $atts['width'] . '%',
                'height' => $atts['height'] . 'vh',
            ],
            'minFov'              => $atts['min_fov'],
            'maxFov'              => $atts['max_fov'],
            'defaultZoomLvl'      => $atts['default_zoom_lavel'],
            'defaultYaw'          => $atts['default_yaw'] . 'deg',
            'defaultPitch'        => $atts['default_pitch'] . 'deg',
            'longitudeRange'      => $atts['longitude_range'],
            'latitudeRange'       => $atts['latitude_range'],
            'autostartDelay'      => $autorotate,
            'autorotateSpeed'     => $autorotate_speed,
            // Back-compat: if a delay was provided, treat as autoplay-on
            'autorotateAutoplay'  => ($atts['autorotate_autoplay'] === 'yes' || $atts['autorotate_delay'] !== ''),
            'fisheye'             => ('yes' === $atts['fish_eye']) ? true : false,
            'mousewheel'          => ('yes' === $atts['mouse_wheel']) ? true : false,
            'mousewheelCtrlKey'   => ('yes' === $atts['mousewheel_ctrl_key']) ? true : false,
            'mousemove'           => ('yes' === $atts['mouse_move']) ? true : false,
            'touchmoveTwoFingers' => ('yes' === $atts['touch_move_two_fingers']) ? true : false,
            'captureCursor'       => ('yes' === $atts['capture_cursor']) ? true : false,
            'moveSpeed'           => $atts['move_speed'],
            'mousewheelSpeed'     => $atts['mouse_wheel_speed'],
            'canvasBackground'    => $atts['canvas_background'],
            // Plugins
            'galleryPlugin'       => $gallery_plugin,
            'compassPlugin'       => $compass_plugin,
            'gyroscopePlugin'     => $gyroscope_plugin,
            'visibleRangePlugin'  => $visible_range_plugin,
        ]);

        $json = wp_json_encode($data);

        return "<div class='xero-psv-container'><div id='" . esc_attr($id) . "' data-settings='" . esc_attr($json) . "'></div></div>";
    }

    /**
     * =========================================================================
     * [psv_tour] — Virtual Tour shortcode (freemium)
     * =========================================================================
     *
     * Attributes:
     *   scenes       — Required JSON array of scene objects:
     *                   [{"name":"…","panorama":"url","thumbnail":"url",
     *                     "caption":"…","yaw":0,"pitch":0,
     *                     "links":"2,3","link_yaws":"80,270"}]
     *   start_scene  — 1-indexed scene number (default 1)
     *   render_mode  — "3d" or "markers" (default "3d") [Pro]
     *   gallery      — Show gallery bar: yes/no (default yes) [Pro]
     *   compass      — Show compass: yes/no (default no) [Pro]
     *   navbar       — Comma-separated navbar items
     *   width        — Container width in % (default 100)
     *   height       — Container height in vh (default 80)
     *
     * Free: basic tour with scenes, navigation, caption navbar
     * Pro:  gallery, compass, render_mode, zoom, fullscreen
     *
     * Example:
     *   [psv_tour scenes='[{"name":"Lobby","panorama":"lobby.jpg","links":"2"},
     *   {"name":"Room","panorama":"room.jpg","links":"1"}]']
     */
    public function render_tour_shortcode($atts, $content = null) {
        wp_enqueue_script('psv-main');
        wp_enqueue_style('psv-style');
        self::$instance_count++;

        $is_pro = $this->is_pro_activated();

        $default = [
            'scenes'       => '',
            'start_scene'  => 1,
            'render_mode'  => '3d',
            'gallery'      => 'yes',
            'compass'      => 'no',
            'navbar'        => 'zoom,caption,fullscreen',
            'width'        => 100,
            'height'       => 80,
            'use_original' => 'yes',
        ];

        $atts = shortcode_atts($default, $atts, 'psv_tour');

        $use_original = ($atts['use_original'] !== 'no');

        if (empty($atts['scenes'])) {
            return '<p style="color:#999;text-align:center;">' . esc_html__('Please provide a scenes attribute for [psv_tour].', 'photo-sphere-viewer') . '</p>';
        }

        $scenes_raw = json_decode(wp_unslash($atts['scenes']), true);
        if (!is_array($scenes_raw) || empty($scenes_raw)) {
            return '<p style="color:#c00;text-align:center;">' . esc_html__('Invalid scenes JSON in [psv_tour].', 'photo-sphere-viewer') . '</p>';
        }

        // Build VirtualTourPlugin nodes
        $nodes = [];
        $total = count($scenes_raw);
        foreach ($scenes_raw as $i => $scene) {
            if (empty($scene['panorama'])) continue;

            $scene_panorama_url = ImageResolver::resolve_url($scene['panorama'], $use_original, 'tour-scene');

            $node = [
                'id'        => 'scene-' . ($i + 1),
                'panorama'  => $scene_panorama_url,
                'name'      => $scene['name'] ?? ('Scene ' . ($i + 1)),
                'thumbnail' => $scene['thumbnail'] ?? $scene_panorama_url,
                'links'     => [],
            ];

            if (!empty($scene['caption'])) {
                $node['caption'] = $scene['caption'];
            }

            $yaw   = isset($scene['yaw']) ? (float) $scene['yaw'] : 0;
            $pitch = isset($scene['pitch']) ? (float) $scene['pitch'] : 0;
            if ($yaw || $pitch) {
                $node['options'] = [
                    'defaultYaw'   => $yaw . 'deg',
                    'defaultPitch' => $pitch . 'deg',
                ];
            }

            // Parse links
            if (!empty($scene['links'])) {
                $linked = array_map('trim', explode(',', $scene['links']));
                $yaws   = !empty($scene['link_yaws'])
                    ? array_map('trim', explode(',', $scene['link_yaws']))
                    : [];

                foreach ($linked as $li => $target_num) {
                    $target_num = (int) $target_num;
                    if ($target_num < 1 || $target_num > $total) continue;

                    $link_yaw = (isset($yaws[$li]) && $yaws[$li] !== '')
                        ? (float) $yaws[$li]
                        : (count($linked) > 1 ? -180 + ($li * (360 / count($linked))) : 0);

                    $node['links'][] = [
                        'nodeId'   => 'scene-' . $target_num,
                        'position' => [
                            'yaw'   => $link_yaw . 'deg',
                            'pitch' => '0deg',
                        ],
                    ];
                }
            }

            $nodes[] = $node;
        }

        if (empty($nodes)) {
            return '<p style="color:#999;text-align:center;">' . esc_html__('No valid scenes found.', 'photo-sphere-viewer') . '</p>';
        }

        $id = wp_unique_id('xero-psv-tour-');

        // Filter navbar items — Pro features gated
        $pro_navbar_items = ['zoom', 'fullscreen', 'gallery', 'download', 'autorotate'];
        $navbar_options = array_map('trim', explode(',', $atts['navbar']));
        if (!$is_pro) {
            $navbar_options = array_filter($navbar_options, function ($item) use ($pro_navbar_items) {
                return !in_array($item, $pro_navbar_items, true);
            });
            $navbar_options = array_values($navbar_options);
        }

        // Gallery items (Pro only)
        $gallery_plugin = null;
        if ($is_pro && 'yes' === $atts['gallery']) {
            $navbar_options[] = 'gallery';
            $gallery_items = [];
            foreach ($nodes as $node) {
                $gallery_items[] = [
                    'id'        => $node['id'],
                    'name'      => $node['name'],
                    'panorama'  => $node['panorama'],
                    'thumbnail' => $node['thumbnail'],
                ];
            }
            $gallery_plugin = [
                'items'         => $gallery_items,
                'visibleOnLoad' => true,
                'hideOnClick'   => true,
                'thumbnailSize' => ['width' => 200, 'height' => 100],
            ];
        }

        // Compass (Pro only)
        $compass_plugin = null;
        if ($is_pro && 'yes' === $atts['compass']) {
            $compass_plugin = ['size' => '120px'];
        }

        $start_node_id = 'scene-' . max(1, (int) $atts['start_scene']);

        $data = array_filter([
            'container'         => $id,
            'navbar'            => $navbar_options,
            'canvasBackground'  => '#333',
            'size'              => [
                'width'  => $atts['width'] . '%',
                'height' => $atts['height'] . 'vh',
            ],
            'virtualTourPlugin' => [
                'nodes'       => $nodes,
                'startNodeId' => $start_node_id,
                'renderMode'  => $is_pro ? $atts['render_mode'] : '3d',
            ],
            'galleryPlugin'     => $gallery_plugin,
            'compassPlugin'     => $compass_plugin,
        ]);

        $json = wp_json_encode($data);

        return "<div class='xero-psv-container'><div id='" . esc_attr($id) . "' data-settings='" . esc_attr($json) . "'></div></div>";
    }

    /**
     * =========================================================================
     * [psv_video] — 360° Video shortcode (freemium)
     * =========================================================================
     *
     * Attributes:
     *   src      — Video URL (required)
     *   caption  — Caption text
     *   autoplay — yes/no (default no) [Pro]
     *   muted    — yes/no (default yes)
     *   loop     — yes/no (default no) [Pro]
     *   navbar   — Comma-separated navbar items
     *   width    — Container width in % (default 100)
     *   height   — Container height in vh (default 80)
     *
     * Free: basic playback with caption, muted, videoPlay/videoTime/videoVolume
     * Pro:  autoplay, loop, zoom, fullscreen, download
     *
     * Example:
     *   [psv_video src="https://example.com/360-video.mp4" muted="yes" autoplay="no"]
     */
    public function render_video_shortcode($atts, $content = null) {
        wp_enqueue_script('psv-main');
        wp_enqueue_style('psv-style');
        self::$instance_count++;

        $is_pro = $this->is_pro_activated();

        $default = [
            'src'      => PSV_ASSETS_URL . 'videos/photo-sphere-viewer.mp4',
            'caption'  => '',
            'autoplay' => 'no',
            'muted'    => 'yes',
            'loop'     => 'no',
            'navbar'   => 'videoPlay,videoTime,zoom,caption,fullscreen,videoVolume',
            'width'    => 100,
            'height'   => 80,
        ];

        $atts = shortcode_atts($default, $atts, 'psv_video');

        if (empty($atts['src'])) {
            return '<p style="color:#999;text-align:center;">' . esc_html__('Please provide a src attribute for [psv_video].', 'photo-sphere-viewer') . '</p>';
        }

        $id = wp_unique_id('xero-psv-video-');

        // Filter navbar items — Pro features gated
        $pro_navbar_items = ['zoom', 'fullscreen', 'download'];
        $navbar_options = array_map('trim', explode(',', $atts['navbar']));
        if (!$is_pro) {
            $navbar_options = array_filter($navbar_options, function ($item) use ($pro_navbar_items) {
                return !in_array($item, $pro_navbar_items, true);
            });
            $navbar_options = array_values($navbar_options);
        }

        $data = array_filter([
            'container'        => $id,
            'caption'          => $atts['caption'],
            'navbar'           => $navbar_options,
            'canvasBackground' => '#000',
            'size'             => [
                'width'  => $atts['width'] . '%',
                'height' => $atts['height'] . 'vh',
            ],
            'isVideo'          => true,
            'videoSource'      => $atts['src'],
            'videoPlugin'      => [
                'autoplay' => $is_pro && ('yes' === $atts['autoplay']),
                'muted'    => ('yes' === $atts['muted']),
                'loop'     => $is_pro && ('yes' === $atts['loop']),
            ],
        ]);

        $json = wp_json_encode($data);

        return "<div class='xero-psv-container'><div id='" . esc_attr($id) . "' data-settings='" . esc_attr($json) . "'></div></div>";
    }

    /**
     * =========================================================================
     * [psv_ar] — AR / 3D Model Viewer shortcode (freemium)
     * =========================================================================
     *
     * Free attributes:
     *   src             — Required. URL to a .glb or .gltf model file.
     *   poster          — Thumbnail image URL shown while the model loads.
     *   alt             — Alt text for the model (default: '3D Model').
     *   width           — Viewer width  (default: 100%).
     *   height          — Viewer height (default: 500px).
     *   auto_rotate     — yes/no — auto-rotate the model (default: yes).
     *   shadow_intensity — 0–10 shadow depth (default: 1).
     *
     * Pro attributes (ignored unless PSV Pro is active):
     *   env             — HDR environment image URL for lighting/reflections.
     *   skybox          — Skybox image URL for scene background.
     *   camera_orbit    — Camera orbit string, e.g. "45deg 55deg 4m".
     *   disable_zoom    — yes/no — disable zoom gesture (default: no).
     *   disable_tap     — yes/no — disable tap-to-rotate (default: no).
     *
     * Example:
     *   [psv_ar src="https://example.com/model.glb" auto_rotate="yes" height="400px"]
     */
    public function render_ar_shortcode($atts, $content = null) {
        // Register & enqueue the model-viewer script on demand.
        if (!wp_script_is('psv-ar-model-viewer', 'registered')) {
            wp_register_script(
                'psv-ar-model-viewer',
                'https://ajax.googleapis.com/ajax/libs/model-viewer/3.4.0/model-viewer.min.js',
                [],
                '3.4.0',
                true
            );
        }
        wp_enqueue_script('psv-ar-model-viewer');

        self::$instance_count++;
        $is_pro = $this->is_pro_activated();

        $default = [
            // Free
            'src'              => '',
            'poster'           => '',
            'alt'              => esc_html__('3D Model', 'photo-sphere-viewer'),
            'width'            => '100%',
            'height'           => '500px',
            'auto_rotate'      => 'yes',
            'shadow_intensity' => '1',
            // Pro
            'env'              => '',
            'skybox'           => '',
            'camera_orbit'     => '',
            'disable_zoom'     => 'no',
            'disable_tap'      => 'no',
        ];

        $atts = shortcode_atts($default, $atts, 'psv_ar');

        if (empty($atts['src'])) {
            return '<p style="color:#999;text-align:center;border:2px dashed #ddd;padding:20px;">'
                . esc_html__('Please provide a src attribute for [psv_ar]. Example: src="https://example.com/model.glb"', 'photo-sphere-viewer')
                . '</p>';
        }

        // ── Build <model-viewer> attribute string ─────────────────────────────
        $mv_attrs = [
            'src'              => esc_url($atts['src']),
            'alt'              => esc_attr($atts['alt']),
            'shadow-intensity' => esc_attr($atts['shadow_intensity']),
            'camera-controls'  => '',
            'touch-action'     => 'pan-y',
            'tone-mapping'     => 'neutral',
            'ar'               => '',
            'style'            => 'width:100%;height:' . esc_attr($atts['height']) . ';display:block;',
        ];

        if (!empty($atts['poster'])) {
            $mv_attrs['poster'] = esc_url($atts['poster']);
        }

        if ('yes' === $atts['auto_rotate']) {
            $mv_attrs['auto-rotate'] = '';
        }

        // Pro-only attributes
        if ($is_pro) {
            if (!empty($atts['env'])) {
                $mv_attrs['environment-image'] = esc_url($atts['env']);
            }
            if (!empty($atts['skybox'])) {
                $mv_attrs['skybox-image'] = esc_url($atts['skybox']);
            }
            if (!empty($atts['camera_orbit'])) {
                $mv_attrs['camera-orbit'] = esc_attr($atts['camera_orbit']);
            }
            if ('yes' === $atts['disable_zoom']) {
                $mv_attrs['disable-zoom'] = '';
            }
            if ('yes' === $atts['disable_tap']) {
                $mv_attrs['disable-tap'] = '';
            }
        }

        $attr_string = '';
        foreach ($mv_attrs as $key => $value) {
            if ('' === $value) {
                $attr_string .= ' ' . $key;
            } else {
                $attr_string .= ' ' . $key . '="' . $value . '"';
            }
        }

        $wrapper_style = 'width:' . esc_attr($atts['width']) . ';';

        return '<div class="psv-ar-viewer-wrapper" style="' . $wrapper_style . '">'
            . '<model-viewer' . $attr_string . '></model-viewer>'
            . '</div>';
    }
}
