<?php
session_start();
$id_user = $_SESSION['id_user'];
$id_virtualtour = $_SESSION['id_virtualtour_sel'];
$_SESSION['tab_edit_room']='preview';
session_write_close();
$id_room = $_GET['id'];
$room = get_room($id_room,$id_user);
$panorama_image = $room['panorama_image'];
$s3_params = check_s3_tour_enabled($id_virtualtour);
$s3_enabled = false;
$s3_url = "";
if(!empty($s3_params)) {
    $s3_bucket_name = $s3_params['bucket'];
    $s3_region = $s3_params['region'];
    $s3_url = init_s3_client($s3_params);
    if($s3_url!==false) {
        $s3_enabled = true;
    }
}
if($s3_enabled) {
    $panorama_url = $s3_url."viewer/panoramas/$panorama_image";
} else {
    $panorama_url = "../viewer/panoramas/$panorama_image";
}
?>

<?php if(!$room): ?>
    <div class="text-center">
        <div class="error mx-auto" data-text="401">401</div>
        <p class="lead text-gray-800 mb-5"><?php echo _("Permission denied"); ?></p>
        <p class="text-gray-500 mb-0"><?php echo _("It looks like that you do not have permission to access this page"); ?></p>
        <a href="index.php?p=dashboard">← <?php echo _("Back to Dashboard"); ?></a>
    </div>
    <script>
        $('.vt_select_header').remove();
    </script>
    <?php die(); endif; ?>

<style>
    #app-container {
        display: flex;
        flex-direction: column;
        height: 100%;
        background-color: #f8f9fa;
    }
    #html-buttons-container {
        flex-shrink: 0;
        display: flex;
        justify-content: space-between;
        align-items: flex-start;
        flex-wrap: wrap;
        padding: 10px;
        background-color: #f0f0f0;
        border-bottom: 1px solid #dee2e6;
    }
    .buttons-group-left, .buttons-group-right {
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        gap: 5px;
    }
    #html-buttons-container .btn {
        display: inline-flex;
        align-items: center;
        justify-content: flex-start;
        box-shadow: 0 1px 2px rgba(0,0,0,0.05);
        border-radius: 0.25rem;
        min-height: 31px;
    }
    #html-buttons-container .btn i {
        margin-right: 8px;
        width: 16px;
        text-align: center;
    }
    #showInstructionsBtn {
        justify-content: center;
    }
    #showInstructionsBtn i {
        margin-right: 0 !important;
    }
    #main-content-area {
        flex-grow: 1;
        display: flex;
        padding: 10px;
        overflow: hidden;
    }
    #canvas-container {
        flex-grow: 1;
        border: 1px solid #ccc;
        overflow: hidden;
        position: relative;
        background-color: #e9e9e9;
        cursor: grab;
        border-radius: 0.25rem;
    }
    #imageCanvas {
        display: block;
        width: 100%;
        height: 100%;
        border-radius: 0.25rem;
    }
    #loader {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background-color: rgba(255, 255, 255, 0.8);
        z-index: 20;
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        border-radius: 0.25rem;
    }
    #loader .spinner-border {
        width: 3rem;
        height: 3rem;
    }
    #loader p {
        margin-top: 10px;
        font-size: 1.1rem;
        color: #333;
    }
    .modal-body ul {
        padding-left: 20px;
    }
    .modal-body li {
        margin-bottom: 5px;
    }
</style>

<div id="app-container">
    <div id="html-buttons-container">
        <div class="buttons-group-left">
            <button id="startPolygonBtn" class="btn btn-primary btn-sm">
                <i class="fas fa-pencil-alt"></i> <span id="startPolygonBtnLabel"><?php echo _("Start Drawing"); ?></span>
            </button>
            <button id="resetPolygonsBtn" class="btn btn-warning btn-sm">
                <i class="fas fa-undo"></i> <?php echo _("Clear Drawing"); ?>
            </button>
            <button id="applyBlurBtn" class="btn btn-success btn-sm <?php echo ($demo) ? 'disabled_d' : ''; ?>" title="Apply blur" disabled>
                <i class="fas fa-magic"></i> <?php echo _("Apply Blur"); ?>
            </button>
        </div>

        <div class="buttons-group-right">
            <button id="showInstructionsBtn" class="btn btn-info btn-sm">
                <i class="fas fa-question-circle"></i>
            </button>
            <button id="resetImageBtn" data-toggle="modal" data-target="#modal_revert_original" id="btn_revert_original" class="btn btn-danger btn-sm <?php echo ($room['blur']==0) ? 'disabled' : ''; ?>">
                <i class="fas fa-sync-alt"></i> <?php echo _("Revert to Original"); ?>
            </button>
            <a href="index.php?p=edit_room&id=<?php echo $id_room; ?>" id="returnToRoomBtn" class="btn btn-secondary btn-sm">
                <i class="fas fa-door-open"></i> <?php echo _("Back to Room"); ?>
            </a>
        </div>
    </div>

    <div id="main-content-area">
        <div id="canvas-container">
            <div id="loader">
                <div class="spinner-border text-primary" role="status"></div>
                <p><?php echo _("Loading image..."); ?></p>
            </div>
            <canvas id="imageCanvas"></canvas>
        </div>
    </div>
</div>

<div class="modal" id="instructionModal" tabindex="-1" role="dialog" aria-labelledby="instructionModalLabel" aria-hidden="true">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="instructionModalLabel"><?php echo _("Quick Instructions"); ?></h5>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
            <div class="modal-body">
                <p><?php echo _("This tool allows you to draw polygons on an image to select areas for blurring."); ?></p>
                <h6><?php echo _("How to Draw:"); ?></h6>
                <ul>
                    <li><?php echo _("Click the <strong>Start Drawing</strong> button."); ?></li>
                    <li><?php echo _("Click on the image to place the vertices of your polygon."); ?></li>
                    <li><?php echo _("To close a polygon:"); ?>
                        <ul>
                            <li><?php echo _("Click near the first vertex."); ?></li>
                            <li><?php echo _("Double-click after placing at least 3 vertices."); ?></li>
                            <li><?php echo _("Click the <strong>End Drawing</strong> button."); ?></li>
                        </ul>
                    </li>
                </ul>
                <p><?php echo _("Once you have drawn your polygon(s), click the <strong>Apply Blur</strong> button to process the selected areas."); ?></p>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-primary" data-dismiss="modal"><?php echo _("Got it!"); ?></button>
            </div>
        </div>
    </div>
</div>

<div id="modal_apply_blur" class="modal" tabindex="-1" role="dialog" data-backdrop="static">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title"><?php echo _("APPLY BLUR"); ?></h5>
            </div>
            <div class="modal-body">
                <p id="blur_loading_msg" style="display:none"><i class="fas fa-spin fa-circle-notch"></i> <?php echo _("Creating blur effect in progress, please wait ..."); ?></p>
                <p id="blur_confirm_msg"><?php echo _("Do you really want to apply blur to the drawn polygons?"); ?></p>
            </div>
            <div class="modal-footer">
                <button <?php echo ($demo) ? 'disabled':''; ?> id="btn_modal_apply_blur" onclick="apply_blur();" type="button" class="btn btn-success"><i class="fas fa-check"></i> <?php echo _("Yes, Apply Blur"); ?></button>
                <button type="button" class="btn btn-secondary" data-dismiss="modal"><i class="fas fa-times"></i> <?php echo _("Close"); ?></button>
            </div>
        </div>
    </div>
</div>

<div id="modal_revert_original" class="modal" tabindex="-1" role="dialog" data-backdrop="static">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title"><?php echo _("REVERT TO ORIGINAL"); ?></h5>
            </div>
            <div class="modal-body">
                <p><?php echo _("Are you sure you want to restore the original image?"); ?></p>
            </div>
            <div class="modal-footer">
                <button <?php echo ($demo) ? 'disabled':''; ?> id="btn_apply_revert_original" onclick="revert_original();" type="button" class="btn btn-danger"><i class="fas fa-reply"></i> <?php echo _("Yes, Revert"); ?></button>
                <button type="button" class="btn btn-secondary" data-dismiss="modal"><i class="fas fa-times"></i> <?php echo _("Close"); ?></button>
            </div>
        </div>
    </div>
</div>

<script>
    (function($) {
        "use strict"; // Start of use strict
        window.id_room = <?php echo $id_room; ?>;
        window.s3_enabled = <?php echo ($s3_enabled) ? 1 : 0; ?>;
        window.s3_url = '<?php echo $s3_url; ?>';
        window.polygons_blur = [];
        var panorama_load = new Image();
        if(window.s3_enabled==1) {
            var panorama_url = window.s3_url+'viewer/panoramas/<?php echo $panorama_image; ?>';
        } else {
            var panorama_url = '../viewer/panoramas/<?php echo $panorama_image; ?>';
        }
        $(document).ready(function () {
            try {
                const canvas = document.getElementById('imageCanvas');
                const ctx = canvas.getContext('2d');
                const $canvasContainer = $('#canvas-container');
                const $loader = $('#loader');

                const $startPolygonBtn = $('#startPolygonBtn');
                const $startPolygonBtnLabel = $('#startPolygonBtnLabel');
                const $resetPolygonsBtn = $('#resetPolygonsBtn');
                const $applyBlurBtn = $('#applyBlurBtn');
                const $resetImageBtn = $('#resetImageBtn');
                const $showInstructionsBtn = $('#showInstructionsBtn');
                let deleteIconRect = null;
                const deleteIconRadius = 9;
                const deleteIconHitboxPadding = 4;

                function setCanvasDimensions() {
                    var footer_h = $('.sticky-footer').height();
                    var container_h = $('#content-wrapper').height() - 95 - footer_h;
                    $('#app-container').css('height', container_h + 'px');
                    const newWidth = $canvasContainer.innerWidth();
                    const newHeight = $canvasContainer.innerHeight();
                    if (canvas.width !== newWidth || canvas.height !== newHeight) {
                        canvas.width = newWidth;
                        canvas.height = newHeight;
                        return true;
                    }
                    return false;
                }

                setCanvasDimensions();

                function debounce(func, wait, immediate) {
                    var timeout;
                    return function() {
                        var context = this, args = arguments;
                        var later = function() {
                            timeout = null;
                            if (!immediate) func.apply(context, args);
                        };
                        var callNow = immediate && !timeout;
                        clearTimeout(timeout);
                        timeout = setTimeout(later, wait);
                        if (callNow) func.apply(context, args);
                    };
                };

                function clampPointToImage(point) {
                    if (!image.complete || image.naturalWidth === 0 || image.naturalHeight === 0) {
                        return point;
                    }
                    return {
                        x: Math.max(0, Math.min(point.x, image.naturalWidth)),
                        y: Math.max(0, Math.min(point.y, image.naturalHeight))
                    };
                }

                function clampOffsets() {
                    if (!image.complete || image.naturalWidth === 0 || image.naturalHeight === 0 || scale === 0 || canvas.width === 0 || canvas.height === 0) {
                        return;
                    }
                    const imageWidthScaled = image.naturalWidth * scale;
                    const imageHeightScaled = image.naturalHeight * scale;

                    if (imageWidthScaled <= canvas.width) {
                        offsetX = Math.max(0, Math.min(offsetX, canvas.width - imageWidthScaled));
                    } else {
                        offsetX = Math.max(canvas.width - imageWidthScaled, Math.min(offsetX, 0));
                    }

                    if (imageHeightScaled <= canvas.height) {
                        offsetY = Math.max(0, Math.min(offsetY, canvas.height - imageHeightScaled));
                    } else {
                        offsetY = Math.max(canvas.height - imageHeightScaled, Math.min(offsetY, 0));
                    }
                }

                function handleResize() {
                    setCanvasDimensions();
                    if (image.complete && image.naturalWidth > 0 && scale > 0) {
                        clampOffsets();
                    }
                    draw();
                }

                $(window).on('resize', debounce(handleResize, 100));

                const image = new Image();
                image.crossOrigin = "Anonymous";

                let scale = 1.0;
                let offsetX = 0;
                let offsetY = 0;
                let currentPolygonPoints = [];
                let isDrawing = false;
                let selectedPolygonIndex = -1;
                let selectedVertexIndex = -1;
                let isDraggingVertex = false;
                let isDraggingPolygon = false;
                let isPanning = false;
                let lastMouseX, lastMouseY;
                let liveMousePos = null;
                let initialDragMousePos = { x: 0, y: 0 };

                const vertexRadius = 5;
                const startPointTolerance = 10;
                const zoomSensitivity = 0.1;
                const lineClickTolerance = 5;

                image.onload = function() {
                    $loader.hide();
                    setCanvasDimensions();

                    if (canvas.width === 0 || canvas.height === 0 || image.naturalWidth === 0 || image.naturalHeight === 0) {
                        draw();
                        return;
                    }
                    const hRatio = canvas.width / image.naturalWidth;
                    const vRatio = canvas.height / image.naturalHeight;
                    scale = Math.min(hRatio, vRatio, 1.0);

                    offsetX = (canvas.width - (image.naturalWidth * scale)) / 2;
                    offsetY = (canvas.height - (image.naturalHeight * scale)) / 2;

                    clampOffsets();
                    draw();
                };
                image.onerror = function() {
                    $loader.hide();
                    console.error("Error loading the image:", image.src);
                    if (ctx) {
                        ctx.clearRect(0,0,canvas.width,canvas.height);
                        ctx.fillStyle = 'rgba(200,200,200,0.8)';
                        ctx.fillRect(0,0,canvas.width, canvas.height);
                        ctx.fillStyle = 'black';
                        ctx.textAlign = 'center';
                        ctx.textBaseline = 'middle';
                        ctx.font = "16px Arial";
                        ctx.fillText("Image loading error.", canvas.width/2, canvas.height/2);
                    }
                };

                $loader.show();
                image.src = panorama_url;

                function getMousePos(event) {
                    const rect = canvas.getBoundingClientRect();
                    return {
                        x: event.clientX - rect.left,
                        y: event.clientY - rect.top
                    };
                }
                function canvasToImageCoords(canvasX, canvasY) { if(scale === 0) return {x:0, y:0}; return { x: (canvasX - offsetX) / scale, y: (canvasY - offsetY) / scale }; }
                function imageToCanvasCoords(imageX, imageY) { return { x: imageX * scale + offsetX, y: imageY * scale + offsetY }; }

                function isPointInPolygon(point, polygonVertices) { if (!polygonVertices || polygonVertices.length < 4) return false; let inside = false; const x = point.x; const y = point.y; for (let i = 0, j = polygonVertices.length - 2; i < polygonVertices.length - 1; j = i++) { const xi = polygonVertices[i].x, yi = polygonVertices[i].y; const xj = polygonVertices[j].x, yj = polygonVertices[j].y; if (((yi > y) !== (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi)) inside = !inside; } return inside; }
                function getDistanceToSegment(p, v, w) { const l2 = (v.x - w.x)**2 + (v.y - w.y)**2; if (l2 === 0) return Math.sqrt((p.x - v.x)**2 + (p.y - v.y)**2); let t = ((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y)) / l2; t = Math.max(0, Math.min(1, t)); const closestPoint = { x: v.x + t * (w.x - v.x), y: v.y + t * (w.y - v.y) }; return Math.sqrt((p.x - closestPoint.x)**2 + (p.y - closestPoint.y)**2); }

                function updateButtonStates() {
                    if (isDrawing) {
                        $startPolygonBtnLabel.text(window.backend_labels.end_drawing);
                    } else {
                        $startPolygonBtnLabel.text(window.backend_labels.start_drawing);
                    }
                    $resetPolygonsBtn.prop('disabled', polygons_blur.length === 0 && currentPolygonPoints.length === 0);
                    $applyBlurBtn.prop('disabled', polygons_blur.length === 0);
                }

                function updateCursorStateBasedOnHover(mouseCanvasPos) {
                    let newCursor = 'grab';

                    if (mouseCanvasPos && selectedPolygonIndex !== -1 && deleteIconRect) {
                        const dx = mouseCanvasPos.x - deleteIconRect.cx;
                        const dy = mouseCanvasPos.y - deleteIconRect.cy;
                        if (dx * dx + dy * dy <= deleteIconRect.radius * deleteIconRect.radius) {
                            newCursor = 'pointer';
                            $canvasContainer.css('cursor', newCursor);
                            return;
                        }
                    }

                    if (isDrawing) {
                        newCursor = 'crosshair';
                        if (mouseCanvasPos && currentPolygonPoints.length >= 3) {
                            const firstPoint = currentPolygonPoints[0];
                            const firstPointCanvas = imageToCanvasCoords(firstPoint.x, firstPoint.y);
                            const distToStart = Math.sqrt(Math.pow(mouseCanvasPos.x - firstPointCanvas.x, 2) + Math.pow(mouseCanvasPos.y - firstPointCanvas.y, 2));
                            if (distToStart < startPointTolerance) {
                                newCursor = 'pointer';
                            }
                        }
                    } else if (isPanning) {
                        newCursor = 'grabbing';
                    } else if (isDraggingPolygon || isDraggingVertex) {
                        newCursor = 'move';
                    } else if (selectedPolygonIndex !== -1 && mouseCanvasPos) {
                        newCursor = 'move';
                        const poly = polygons_blur[selectedPolygonIndex];
                        let onVertex = false;
                        for (let j = 0; j < poly.length; j++) {
                            const vertexCanvas = imageToCanvasCoords(poly[j].x, poly[j].y);
                            if (Math.sqrt(Math.pow(mouseCanvasPos.x - vertexCanvas.x, 2) + Math.pow(mouseCanvasPos.y - vertexCanvas.y, 2)) < vertexRadius + 2) {
                                newCursor = 'pointer';
                                onVertex = true; break;
                            }
                        }
                        if (!onVertex) {
                            for (let j = 0; j < poly.length - 1; j++) {
                                const p1Canvas = imageToCanvasCoords(poly[j].x, poly[j].y);
                                const p2Canvas = imageToCanvasCoords(poly[j+1].x, poly[j+1].y);
                                if (getDistanceToSegment(mouseCanvasPos, p1Canvas, p2Canvas) < lineClickTolerance) {
                                    newCursor = 'copy';
                                    break;
                                }
                            }
                        }
                    }
                    $canvasContainer.css('cursor', newCursor);
                }

                function draw() {
                    if ($loader.is(':visible') && (!image.complete || image.naturalWidth === 0)) {
                        if (ctx && canvas.width > 0 && canvas.height > 0) {
                            ctx.clearRect(0, 0, canvas.width, canvas.height);
                        }
                        return;
                    }

                    if (canvas.width === 0 || canvas.height === 0 || !ctx) return;
                    ctx.clearRect(0, 0, canvas.width, canvas.height);

                    if (image.complete && image.naturalWidth > 0 && image.naturalHeight > 0) {
                        ctx.save();
                        ctx.translate(offsetX, offsetY);
                        ctx.scale(scale, scale);
                        try {
                            ctx.drawImage(image, 0, 0, image.naturalWidth, image.naturalHeight);
                        } catch (e) {
                            console.error("Error drawing image:", e);
                            ctx.restore();
                            ctx.fillStyle = '#dddddd'; ctx.fillRect(0,0, canvas.width, canvas.height);
                            ctx.fillStyle = 'black'; ctx.textAlign = 'center';
                            ctx.fillText("Image rendering error.", canvas.width/2, canvas.height/2);
                            ctx.save();
                            ctx.translate(offsetX, offsetY); ctx.scale(scale, scale);
                        }

                        polygons_blur.forEach((polygon, polyIndex) => {
                            ctx.beginPath();
                            polygon.forEach((p, pointIndex) => {
                                (pointIndex === 0) ? ctx.moveTo(p.x, p.y) : ctx.lineTo(p.x, p.y);
                            });
                            if (polygon.length > 1) ctx.closePath();

                            ctx.lineWidth = (polyIndex === selectedPolygonIndex ? 3 : 2) / scale;
                            ctx.strokeStyle = polyIndex === selectedPolygonIndex ? 'rgba(255, 0, 0, 0.8)' : 'rgba(0, 0, 255, 0.8)';
                            ctx.fillStyle = polyIndex === selectedPolygonIndex ? 'rgba(255, 0, 0, 0.3)' : 'rgba(0, 0, 255, 0.3)';
                            ctx.fill();
                            ctx.stroke();

                            polygon.forEach((p, vertIndex) => {
                                ctx.beginPath();
                                ctx.arc(p.x, p.y, vertexRadius / scale, 0, 2 * Math.PI);
                                if (polyIndex === selectedPolygonIndex && vertIndex === selectedVertexIndex) ctx.fillStyle = 'yellow';
                                else if (polyIndex === selectedPolygonIndex) ctx.fillStyle = 'red';
                                else ctx.fillStyle = 'blue';
                                ctx.fill();
                            });
                        });

                        if (isDrawing && currentPolygonPoints.length > 0) {
                            if (currentPolygonPoints.length >= 2 && liveMousePos) {
                                ctx.beginPath();
                                ctx.moveTo(currentPolygonPoints[0].x, currentPolygonPoints[0].y);
                                for (let i = 1; i < currentPolygonPoints.length; i++) {
                                    ctx.lineTo(currentPolygonPoints[i].x, currentPolygonPoints[i].y);
                                }
                                ctx.lineTo(liveMousePos.x, liveMousePos.y);
                                ctx.fillStyle = 'rgba(0, 220, 0, 0.15)';
                                ctx.fill();
                            }

                            ctx.beginPath();
                            currentPolygonPoints.forEach((p, pointIndex) => {
                                (pointIndex === 0) ? ctx.moveTo(p.x, p.y) : ctx.lineTo(p.x, p.y);
                            });
                            if (liveMousePos) {
                                ctx.lineTo(liveMousePos.x, liveMousePos.y);
                            }

                            ctx.strokeStyle = 'rgba(0, 180, 0, 0.8)';
                            ctx.lineWidth = 2 / scale;
                            ctx.stroke();

                            currentPolygonPoints.forEach((p, pointIndex) => {
                                ctx.fillStyle = (pointIndex === 0) ? 'lime' : 'green';
                                ctx.beginPath();
                                const radius = (pointIndex === 0) ? (vertexRadius + 2) / scale : vertexRadius / scale;
                                ctx.arc(p.x, p.y, radius, 0, 2 * Math.PI);
                                ctx.fill();
                            });
                        }
                        ctx.restore();
                    } else if (!image.complete && !$loader.is(':visible')) {
                        ctx.fillStyle = '#dddddd'; ctx.fillRect(0,0, canvas.width, canvas.height);
                        ctx.fillStyle = 'black'; ctx.textAlign = 'center';
                        ctx.fillText("Image not available.", canvas.width/2, canvas.height/2);
                    }

                    deleteIconRect = null;
                    if (selectedPolygonIndex !== -1 && polygons_blur[selectedPolygonIndex] && polygons_blur[selectedPolygonIndex].length > 0) {
                        const poly = polygons_blur[selectedPolygonIndex];

                        let topRightVertex = poly[0];
                        const numPointsToConsider = (poly[0].x === poly[poly.length -1].x && poly[0].y === poly[poly.length-1].y && poly.length > 1) ? poly.length - 1 : poly.length;

                        for (let i = 0; i < numPointsToConsider; i++) {
                            if (poly[i].x > topRightVertex.x) {
                                topRightVertex = poly[i];
                            } else if (poly[i].x === topRightVertex.x && poly[i].y < topRightVertex.y) {
                                topRightVertex = poly[i];
                            }
                        }

                        const iconOffsetAmount = deleteIconRadius * 0.8;
                        const iconCanvasPos = imageToCanvasCoords(topRightVertex.x, topRightVertex.y);

                        const iconCenterX = iconCanvasPos.x + 10 + (iconOffsetAmount / scale);
                        const iconCenterY = iconCanvasPos.y - 10 - (iconOffsetAmount / scale);

                        deleteIconRect = {
                            cx: iconCenterX,
                            cy: iconCenterY,
                            radius: deleteIconRadius + deleteIconHitboxPadding
                        };

                        ctx.save();
                        ctx.beginPath();
                        ctx.arc(iconCenterX, iconCenterY, deleteIconRadius, 0, 2 * Math.PI);
                        ctx.fillStyle = 'rgba(220, 53, 69, 0.9)';
                        ctx.fill();

                        ctx.strokeStyle = 'white';
                        ctx.lineWidth = 2.5;
                        ctx.lineCap = 'round';
                        const xSize = deleteIconRadius * 0.5;
                        ctx.beginPath();
                        ctx.moveTo(iconCenterX - xSize, iconCenterY - xSize);
                        ctx.lineTo(iconCenterX + xSize, iconCenterY + xSize);
                        ctx.moveTo(iconCenterX + xSize, iconCenterY - xSize);
                        ctx.lineTo(iconCenterX - xSize, iconCenterY + xSize);
                        ctx.stroke();
                        ctx.restore();
                    }
                }

                function handleStartPolygonButtonClick() {
                    if ($loader.is(':visible')) return;
                    isDrawing = !isDrawing;
                    if (!isDrawing) {
                        if (currentPolygonPoints.length >= 3) {
                            currentPolygonPoints.push({...currentPolygonPoints[0]});
                            polygons_blur.push([...currentPolygonPoints]);
                            selectedPolygonIndex = polygons_blur.length - 1;
                        }
                        currentPolygonPoints = [];
                        liveMousePos = null;
                    } else {
                        currentPolygonPoints = [];
                        selectedPolygonIndex = -1;
                        selectedVertexIndex = -1;
                    }
                    updateButtonStates();
                    draw();
                }

                function handleApplyBlurButtonClick() {
                    if ($loader.is(':visible')) return;
                    if (polygons_blur.length === 0) {
                        alert("No polygons drawn to apply blur to.");
                        return;
                    }
                    updateButtonStates();
                    $('#modal_apply_blur').modal('show');
                }

                function handleResetPolygonsButtonClick() {
                    if ($loader.is(':visible')) return;
                    polygons_blur = [];
                    currentPolygonPoints = [];
                    liveMousePos = null;
                    selectedPolygonIndex = -1;
                    selectedVertexIndex = -1;
                    isDrawing = false;
                    deleteIconRect = null;
                    updateButtonStates();
                    draw();
                }

                function handleResetImageButtonClick() {
                    if ($loader.is(':visible')) return;
                    console.log("Revert Original Image function called.");
                }

                function handleShowInstructionsButtonClick() {
                    if ($loader.is(':visible')) return;
                    $('#instructionModal').modal('show');
                }

                $startPolygonBtn.on('click', handleStartPolygonButtonClick);
                $resetPolygonsBtn.on('click', handleResetPolygonsButtonClick);
                $applyBlurBtn.on('click', handleApplyBlurButtonClick);
                $resetImageBtn.on('click', handleResetImageButtonClick);
                $showInstructionsBtn.on('click', handleShowInstructionsButtonClick);

                $('#imageCanvas').on('mousedown', function(e) {
                    if ($loader.is(':visible')) return;

                    const mousePos = getMousePos(e);
                    let imageMousePos = canvasToImageCoords(mousePos.x, mousePos.y);
                    lastMouseX = mousePos.x;
                    lastMouseY = mousePos.y;
                    let actionTaken = false;
                    let clickedOnExistingInteractiveElement = false;

                    if (e.button === 2) return;

                    if (selectedPolygonIndex !== -1 && deleteIconRect) {
                        const dx = mousePos.x - deleteIconRect.cx;
                        const dy = mousePos.y - deleteIconRect.cy;
                        if (dx * dx + dy * dy <= deleteIconRect.radius * deleteIconRect.radius) {
                            polygons_blur.splice(selectedPolygonIndex, 1);
                            selectedPolygonIndex = -1;
                            selectedVertexIndex = -1;
                            deleteIconRect = null;
                            actionTaken = true;
                            clickedOnExistingInteractiveElement = true;
                        }
                    }

                    if (!actionTaken && isDrawing) {
                        const clampedImageMousePos = clampPointToImage(imageMousePos);
                        if (currentPolygonPoints.length > 0) {
                            const firstPoint = currentPolygonPoints[0];
                            const firstPointCanvas = imageToCanvasCoords(firstPoint.x, firstPoint.y);
                            const distToStart = Math.sqrt(Math.pow(mousePos.x - firstPointCanvas.x, 2) + Math.pow(mousePos.y - firstPointCanvas.y, 2));

                            if (currentPolygonPoints.length >=3 && distToStart < startPointTolerance) {
                                currentPolygonPoints.push({...firstPoint});
                                polygons_blur.push([...currentPolygonPoints]);
                                currentPolygonPoints = [];
                                isDrawing = false;
                                liveMousePos = null;
                                selectedPolygonIndex = polygons_blur.length -1;
                            } else {
                                currentPolygonPoints.push(clampedImageMousePos);
                            }
                        } else {
                            currentPolygonPoints.push(clampedImageMousePos);
                        }
                        actionTaken = true;
                        clickedOnExistingInteractiveElement = true;
                    } else if (!actionTaken) {
                        for (let i = 0; i < polygons_blur.length && !clickedOnExistingInteractiveElement; i++) {
                            const poly = polygons_blur[i];
                            for (let j = 0; j < poly.length; j++) {
                                const vertex = poly[j];
                                const vertexCanvas = imageToCanvasCoords(vertex.x, vertex.y);
                                if (Math.sqrt(Math.pow(mousePos.x - vertexCanvas.x, 2) + Math.pow(mousePos.y - vertexCanvas.y, 2)) < vertexRadius + 3) {
                                    selectedPolygonIndex = i;
                                    selectedVertexIndex = j;
                                    isDraggingVertex = true;
                                    clickedOnExistingInteractiveElement = true;
                                    actionTaken = true;
                                    break;
                                }
                            }
                        }

                        if (!clickedOnExistingInteractiveElement && selectedPolygonIndex !== -1) {
                            const poly = polygons_blur[selectedPolygonIndex];
                            for (let j = 0; j < poly.length - 1; j++) {
                                const p1Canvas = imageToCanvasCoords(poly[j].x, poly[j].y);
                                const p2Canvas = imageToCanvasCoords(poly[j+1].x, poly[j+1].y);
                                if (getDistanceToSegment(mousePos, p1Canvas, p2Canvas) < lineClickTolerance) {
                                    const newVertexPos = clampPointToImage(imageMousePos);
                                    poly.splice(j + 1, 0, newVertexPos);
                                    if (poly.length > 1 && poly[0].x === poly[poly.length-2].x && poly[0].y === poly[poly.length-2].y ) {
                                        poly[poly.length-1] = {...poly[0]};
                                    }
                                    selectedVertexIndex = j + 1;
                                    isDraggingVertex = true;
                                    clickedOnExistingInteractiveElement = true;
                                    actionTaken = true;
                                    break;
                                }
                            }
                        }

                        if (!clickedOnExistingInteractiveElement) {
                            let newlySelectedPolyIdx = -1;
                            for (let i = polygons_blur.length - 1; i >= 0; i--) {
                                if (isPointInPolygon(imageMousePos, polygons_blur[i])) {
                                    newlySelectedPolyIdx = i;
                                    break;
                                }
                            }

                            if (newlySelectedPolyIdx !== -1) {
                                selectedPolygonIndex = newlySelectedPolyIdx;
                                selectedVertexIndex = -1;
                                isDraggingPolygon = true;
                                initialDragMousePos = {...imageMousePos};
                                clickedOnExistingInteractiveElement = true;
                                actionTaken = true;
                            } else {
                                if (selectedPolygonIndex !== -1) {
                                    selectedPolygonIndex = -1;
                                    selectedVertexIndex = -1;
                                    deleteIconRect = null;
                                }
                            }
                        }

                        if (!actionTaken && !clickedOnExistingInteractiveElement) {
                            isPanning = true;
                        }
                    }
                    updateButtonStates();
                    draw();
                    updateCursorStateBasedOnHover(mousePos);
                });

                $('#imageCanvas').on('mousemove', function(e) {
                    if ($loader.is(':visible')) return;

                    const currentCanvasMousePos = getMousePos(e);
                    let needsRedraw = false;

                    if (isDraggingPolygon && selectedPolygonIndex !== -1) {
                        const currentImageMousePos = canvasToImageCoords(currentCanvasMousePos.x, currentCanvasMousePos.y);
                        let dxImage = currentImageMousePos.x - initialDragMousePos.x;
                        let dyImage = currentImageMousePos.y - initialDragMousePos.y;

                        const polyToDrag = polygons_blur[selectedPolygonIndex];

                        if (image.complete && image.naturalWidth > 0 && image.naturalHeight > 0) {
                            let minPotentialX = Infinity, maxPotentialX = -Infinity;
                            let minPotentialY = Infinity, maxPotentialY = -Infinity;

                            for (const p of polyToDrag) {
                                const newX = p.x + dxImage;
                                const newY = p.y + dyImage;
                                minPotentialX = Math.min(minPotentialX, newX);
                                maxPotentialX = Math.max(maxPotentialX, newX);
                                minPotentialY = Math.min(minPotentialY, newY);
                                maxPotentialY = Math.max(maxPotentialY, newY);
                            }

                            if (minPotentialX < 0) dxImage -= minPotentialX;
                            if (maxPotentialX > image.naturalWidth) dxImage -= (maxPotentialX - image.naturalWidth);
                            if (minPotentialY < 0) dyImage -= minPotentialY;
                            if (maxPotentialY > image.naturalHeight) dyImage -= (maxPotentialY - image.naturalHeight);
                        }

                        for (let i = 0; i < polyToDrag.length; i++) {
                            polyToDrag[i].x += dxImage;
                            polyToDrag[i].y += dyImage;
                        }

                        initialDragMousePos.x += dxImage;
                        initialDragMousePos.y += dyImage;

                        needsRedraw = true;
                    } else if (isDraggingVertex && selectedPolygonIndex !== -1 && selectedVertexIndex !== -1) {
                        const imageMouseCoords = canvasToImageCoords(currentCanvasMousePos.x, currentCanvasMousePos.y);
                        const poly = polygons_blur[selectedPolygonIndex];
                        const clampedMouseCoords = clampPointToImage(imageMouseCoords);
                        poly[selectedVertexIndex] = clampedMouseCoords;

                        if (poly.length > 1 && (selectedVertexIndex === 0 || selectedVertexIndex === poly.length - 1) ) {
                            if (selectedVertexIndex === 0) poly[poly.length - 1] = {...clampedMouseCoords};
                            else if (selectedVertexIndex === poly.length - 1) poly[0] = {...clampedMouseCoords};
                        }
                        needsRedraw = true;
                    } else if (isPanning) {
                        const dxCanvas = currentCanvasMousePos.x - lastMouseX;
                        const dyCanvas = currentCanvasMousePos.y - lastMouseY;
                        offsetX += dxCanvas;
                        offsetY += dyCanvas;
                        clampOffsets();
                        needsRedraw = true;
                    }

                    if (isDrawing && currentPolygonPoints.length > 0) {
                        liveMousePos = clampPointToImage(canvasToImageCoords(currentCanvasMousePos.x, currentCanvasMousePos.y));
                        needsRedraw = true;
                    } else {
                        if (liveMousePos !== null) needsRedraw = true;
                        liveMousePos = null;
                    }

                    lastMouseX = currentCanvasMousePos.x;
                    lastMouseY = currentCanvasMousePos.y;

                    if (needsRedraw) draw();
                    updateCursorStateBasedOnHover(currentCanvasMousePos);
                });

                $('#imageCanvas').on('mouseup', function(e) {
                    if ($loader.is(':visible')) return;
                    if (e.button === 2) return;
                    isDraggingVertex = false;
                    isDraggingPolygon = false;
                    isPanning = false;
                    updateCursorStateBasedOnHover(getMousePos(e));
                });

                $('#imageCanvas').on('mouseleave', function(e) {
                    if ($loader.is(':visible')) return;
                    if (isPanning || isDraggingVertex || isDraggingPolygon) {
                        isDraggingVertex = false;
                        isPanning = false;
                        isDraggingPolygon = false;
                        draw();
                    }
                    if (liveMousePos !== null) {
                        liveMousePos = null;
                        draw();
                    }
                    $canvasContainer.css('cursor', 'grab');
                });

                $('#imageCanvas').on('contextmenu', function(e) {
                    if ($loader.is(':visible')) return;
                    e.preventDefault();
                    if (isDrawing || selectedPolygonIndex === -1) return;

                    const mousePos = getMousePos(e);
                    const poly = polygons_blur[selectedPolygonIndex];

                    if (poly.length <= 4) {
                        console.log("Cannot delete vertex, polygon must have at least 3 vertices.");
                        return;
                    }

                    for (let j = 0; j < poly.length -1; j++) {
                        const vertex = poly[j];
                        const vertexCanvas = imageToCanvasCoords(vertex.x, vertex.y);
                        if (Math.sqrt(Math.pow(mousePos.x - vertexCanvas.x, 2) + Math.pow(mousePos.y - vertexCanvas.y, 2)) < vertexRadius + 3) {
                            poly.splice(j, 1);

                            poly.pop();
                            if (poly.length > 0) {
                                poly.push({...poly[0]});
                            } else {
                                polygons_blur.splice(selectedPolygonIndex, 1);
                                selectedPolygonIndex = -1;
                                deleteIconRect = null;
                                break;
                            }

                            if (poly.length <= 3) {
                                polygons_blur.splice(selectedPolygonIndex, 1);
                                selectedPolygonIndex = -1;
                                deleteIconRect = null;
                            }
                            selectedVertexIndex = -1;
                            updateButtonStates();
                            draw();
                            updateCursorStateBasedOnHover(mousePos);
                            return;
                        }
                    }
                });

                $('#imageCanvas').on('dblclick', function(e) {
                    if ($loader.is(':visible')) return;
                    if (isDrawing && currentPolygonPoints.length >= 3) {
                        currentPolygonPoints.push({...currentPolygonPoints[0]});
                        polygons_blur.push([...currentPolygonPoints]);
                        currentPolygonPoints = [];
                        isDrawing = false;
                        liveMousePos = null;
                        selectedPolygonIndex = polygons_blur.length - 1;
                        updateButtonStates();
                        draw();
                        updateCursorStateBasedOnHover(getMousePos(e));
                    }
                });

                function applyZoom(zoomFactor, centerX, centerY) {
                    if ($loader.is(':visible')) return;
                    if (isDrawing) return;
                    if (!image.complete || image.naturalWidth === 0 || image.naturalHeight === 0 || canvas.width === 0 || canvas.height === 0) return;

                    const imagePointX = (centerX - offsetX) / scale;
                    const imagePointY = (centerY - offsetY) / scale;

                    let newProposedScale = scale * zoomFactor;

                    const minScaleToFit = Math.min(canvas.width / image.naturalWidth, canvas.height / image.naturalHeight);
                    newProposedScale = Math.max(minScaleToFit * 0.95, Math.min(newProposedScale, 10));

                    if (scale === newProposedScale) return;

                    scale = newProposedScale;

                    offsetX = centerX - imagePointX * scale;
                    offsetY = centerY - imagePointY * scale;

                    clampOffsets();
                    draw();
                }

                $canvasContainer.on('wheel', function(event) {
                    if ($loader.is(':visible')) return;
                    if (isDrawing) { event.preventDefault(); return; }

                    const originalEv = event.originalEvent;
                    if (!originalEv) return;

                    event.preventDefault();
                    const mousePos = getMousePos(originalEv);
                    let zoomFactor = 1;
                    if (originalEv.deltaY < 0) zoomFactor = 1 + zoomSensitivity;
                    else if (originalEv.deltaY > 0) zoomFactor = 1 - zoomSensitivity;

                    applyZoom(zoomFactor, mousePos.x, mousePos.y);
                });

                updateCursorStateBasedOnHover(null);
                updateButtonStates();

            } catch (e) {
                console.error("Global error caught:", e.name, e.message, e.stack);
                if (typeof $loader !== 'undefined' && $loader) $loader.hide();
                const $body = $('body');
                $body.empty().append(
                    $('<div style="padding: 20px; text-align: center; color: red; font-family: sans-serif;"></div>')
                        .append($('<h1>Critical Application Error</h1>'))
                        .append($('<p>An unexpected error occurred, preventing the application from working. Check the browser console (F12 key) for technical details.</p>'))
                        .append($('<pre style="text-align: left; background: #f0f0f0; padding: 10px; border: 1px solid #ccc; border-radius: 4px; white-space: pre-wrap; word-wrap: break-word; color: #333;"></pre>')
                            .text(`Error Details:\nName: ${e.name}\nMessage: ${e.message}\n\nStack Trace (first steps):\n${e.stack ? e.stack.split('\n').slice(0, 5).join('\n') : 'Not available'}`))
                );
            }
        });
    })(jQuery); // End of use strict

    function apply_blur() {
        var html_btn = $('#btn_modal_apply_blur').html();
        $('#modal_apply_blur .btn').addClass('disabled');
        $('#blur_confirm_msg').hide();
        $('#blur_loading_msg').show();
        $.ajax({
            url: "ajax/apply_blur.php",
            type: "POST",
            data: {
                id_room: window.id_room,
                polygons: JSON.stringify(polygons_blur),
                panorama_image: '<?php echo $panorama_image; ?>'
            },
            async: true,
            success: function (json) {
                $('#modal_apply_blur .btn').removeClass('disabled');
                $('#modal_apply_blur').modal("hide");
                location.reload();
            },
            error: function () {
                $('#btn_modal_apply_blur').html(html_btn);
                $('#blur_confirm_msg').show();
                $('#blur_loading_msg').hide();
                $('#modal_apply_blur .btn').removeClass('disabled');
            }
        });
    }

    function revert_original() {
        var html_btn = $('#btn_apply_revert_original').html();
        $('#modal_revert_original button').addClass('disabled');
        $('#btn_apply_revert_original').html('<i class="fas fa-spin fa-circle-notch" aria-hidden="true"></i>');
        $.ajax({
            url: "ajax/revert_original.php",
            type: "POST",
            data: {
                id_room: id_room,
                panorama_image: '<?php echo $panorama_image; ?>'
            },
            async: true,
            success: function (json) {
                $('#modal_revert_original button').removeClass('disabled');
                $('#modal_revert_original').modal("hide");
                location.reload();
            },
            error: function (xhr) {
                $('#modal_revert_original button').removeClass('disabled');
                $('#btn_apply_revert_original').html(html_btn);
            }
        });
    }
</script>