
<!-- Modal Scanner -->
<div class="modal fade" id="modalScanner" tabindex="-1" role="dialog" aria-labelledby="modalScannerLabel" aria-hidden="true" data-backdrop="static">
    <div class="modal-dialog modal-xl" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="modalScannerLabel"><i class="fas fa-expand"></i> Smart Scanner</h5>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
            <div class="modal-body text-center bg-dark p-0" style="position: relative; overflow: hidden; height: 80vh;">
                <!-- Container for Canvases -->
                <!-- Container for Canvases -->
                <div id="scanner-container" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); box-shadow: 0 0 10px rgba(0,0,0,0.5);">
                    <canvas id="canvas-image" style="position: absolute; left: 0; top: 0; z-index: 10;"></canvas>
                    <canvas id="canvas-overlay" style="position: absolute; left: 0; top: 0; z-index: 20; cursor: crosshair;"></canvas>
                </div>
                <div id="scanner-loading" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%); color: white; display: none; z-index: 50; text-align: center;">
                    <i class="fas fa-spinner fa-spin fa-3x"></i><br><span style="margin-top: 10px; display: block;">Sedang menganalisa...</span>
                </div>
            </div>
            <div class="modal-footer justify-content-between">
                <div>
                     <button type="button" class="btn btn-secondary" id="btnScanRotateLeft" title="Putar Kiri (-90°)"><i class="fas fa-undo"></i></button>
                     <button type="button" class="btn btn-secondary" id="btnScanRotateRight" title="Putar Kanan (+90°)"><i class="fas fa-redo"></i></button>
                     <button type="button" class="btn btn-warning" id="btnScanReset"><i class="fas fa-sync"></i> Reset Sudut</button>
                </div>
                <div>
                    <button type="button" class="btn btn-secondary" data-dismiss="modal">Batal</button>
                    <button type="button" class="btn btn-primary" id="btnScanSave"><i class="fas fa-check"></i> Simpan Hasil Scan</button>
                </div>
            </div>
        </div>
    </div>
</div>

<script>
window.addEventListener('load', function() {
    // Scanner Variables
    var scannerModal = $('#modalScanner');
    var canvasImage = document.getElementById('canvas-image');
    var canvasOverlay = document.getElementById('canvas-overlay');
    var ctxImg = canvasImage.getContext('2d');
    var ctxOver = canvasOverlay.getContext('2d');
    
    var scanner = new jscanify();
    var originalImg = new Image();
    
    // Corner Points (tl, tr, bl, br)
    var corners = [];
    var activePoint = null;
    var isDragging = false;
    
    // Config
    const POINT_RADIUS = 15;
    const POINT_COLOR = '#007bff';
    const LINE_COLOR = '#00ff00';
    const LINE_WIDTH = 3;

    // --- Public Function to Open Scanner ---
    window.openScanner = function(file) {
        if (!file) return;

        // Reset State
        corners = [];
        activePoint = null;
        isDragging = false;
        
        // Show Loading
        $('#scanner-loading').show();
        
        // Logic: Wait for BOTH Image Load AND Modal Shown
        var imgLoaded = false;
        var modalShown = false;

        function checkReady() {
            if (imgLoaded && modalShown) {
                // Defer execution to allow UI (spinner) to render first
                setTimeout(function() {
                    initScanner();
                }, 100);
            }
        }

        // 1. Load Image
        var reader = new FileReader();
        reader.onload = function(e) {
            originalImg.onload = function() {
                imgLoaded = true;
                checkReady();
            };
            originalImg.src = e.target.result;
        };
        reader.readAsDataURL(file);

        // 2. Show Modal & Listen
        scannerModal.off('shown.bs.modal'); // Remove old listeners
        scannerModal.on('shown.bs.modal', function() {
            modalShown = true;
            checkReady();
        });
        
        scannerModal.modal('show');
    };

    function initScanner() {
        // Resize Canvas to fit screen but keep aspect ratio
        var maxWidth = $('#modalScanner .modal-body').width() - 20;
        var maxHeight = $('#modalScanner .modal-body').height() - 20;
        
        var scale = Math.min(maxWidth / originalImg.width, maxHeight / originalImg.height);
        var w = originalImg.width * scale;
        var h = originalImg.height * scale;
        
        canvasImage.width = w;
        canvasImage.height = h;
        canvasOverlay.width = w;
        canvasOverlay.height = h;
        
        // Resize container
        $('#scanner-container').css({ width: w, height: h });
        
        // Draw Image
        ctxImg.drawImage(originalImg, 0, 0, w, h);
        
        // Detect Contour using jscanify
        try {
            // jscanify expects an image element, we can pass originalImg but we need to map coordinates
            // Wait, jscanify uses OpenCV which might not be ready.
            if (typeof cv !== 'undefined' && cv.Mat) {
                // We need to work on the original image for detection, then scale points
                var contour = scanner.findPaper(originalImg); 
                // contour returns { topLeftCorner, topRightCorner, bottomLeftCorner, bottomRightCorner } each {x, y}
                
                if (contour) {
                    corners = [
                        { x: contour.topLeftCorner.x * scale, y: contour.topLeftCorner.y * scale },
                        { x: contour.topRightCorner.x * scale, y: contour.topRightCorner.y * scale },
                        { x: contour.bottomRightCorner.x * scale, y: contour.bottomRightCorner.y * scale }, // Order: tr -> br -> bl ?? No, usually tl, tr, br, bl order for polygon drawing
                        { x: contour.bottomLeftCorner.x * scale, y: contour.bottomLeftCorner.y * scale }
                    ];
                    // Reorder primarily for logic: TL, TR, BR, BL
                     corners = [
                        { x: contour.topLeftCorner.x * scale, y: contour.topLeftCorner.y * scale },
                        { x: contour.topRightCorner.x * scale, y: contour.topRightCorner.y * scale },
                        { x: contour.bottomRightCorner.x * scale, y: contour.bottomRightCorner.y * scale },
                        { x: contour.bottomLeftCorner.x * scale, y: contour.bottomLeftCorner.y * scale }
                    ];

                } else {
                     defaultCorners(w, h);
                }
            } else {
                console.warn("OpenCV not ready yet");
                defaultCorners(w, h);
            }
        } catch(e) {
            console.error("Scanner Error:", e);
             defaultCorners(w, h); // Fallback
        }
        
        $('#scanner-loading').hide();
        drawOverlay();
    }

    function defaultCorners(w, h) {
        // Default 20% margin
        var mX = w * 0.1;
        var mY = h * 0.1;
        corners = [
            { x: mX, y: mY }, // TL
            { x: w - mX, y: mY }, // TR
            { x: w - mX, y: h - mY }, // BR
            { x: mX, y: h - mY } // BL
        ];
    }
    
    function drawOverlay() {
        ctxOver.clearRect(0, 0, canvasOverlay.width, canvasOverlay.height);
        
        if (corners.length < 4) return;
        
        // Draw Lines
        ctxOver.beginPath();
        ctxOver.lineWidth = LINE_WIDTH;
        ctxOver.strokeStyle = LINE_COLOR;
        ctxOver.moveTo(corners[0].x, corners[0].y);
        ctxOver.lineTo(corners[1].x, corners[1].y);
        ctxOver.lineTo(corners[2].x, corners[2].y);
        ctxOver.lineTo(corners[3].x, corners[3].y);
        ctxOver.closePath();
        ctxOver.stroke();
        
        // Draw Points
        ctxOver.fillStyle = POINT_COLOR;
        corners.forEach(p => {
            ctxOver.beginPath();
            ctxOver.arc(p.x, p.y, POINT_RADIUS, 0, Math.PI * 2);
            ctxOver.fill();
            ctxOver.strokeStyle = 'white';
            ctxOver.lineWidth = 2;
            ctxOver.stroke();
        });
    }

    // --- Mouse / Touch Interactivity ---
    
    function getMousePos(evt) {
        var rect = canvasOverlay.getBoundingClientRect();
        return {
            x: (evt.clientX || evt.touches[0].clientX) - rect.left,
            y: (evt.clientY || evt.touches[0].clientY) - rect.top
        };
    }

    function isInside(pos, point) {
        var dx = pos.x - point.x;
        var dy = pos.y - point.y;
        return dx * dx + dy * dy <= POINT_RADIUS * POINT_RADIUS * 2; // Bigger hit area
    }

    canvasOverlay.addEventListener('mousedown', function(e) { handleStart(getMousePos(e)); });
    canvasOverlay.addEventListener('touchstart', function(e) { handleStart(getMousePos(e)); e.preventDefault(); }, {passive: false});

    window.addEventListener('mousemove', function(e) { if(isDragging) handleMove(getMousePos(e)); }); // Window to catch drag out
    canvasOverlay.addEventListener('touchmove', function(e) { if(isDragging) handleMove(getMousePos(e)); e.preventDefault(); }, {passive: false});

    window.addEventListener('mouseup', function() { handleEnd(); });
    window.addEventListener('touchend', function() { handleEnd(); });

    function handleStart(pos) {
        activePoint = null;
        corners.forEach((p, i) => {
            if (isInside(pos, p)) {
                activePoint = i;
                isDragging = true;
            }
        });
    }

    function handleMove(pos) {
        if (activePoint !== null) {
            // Constrain to canvas?? Optional but good
            corners[activePoint].x = pos.x;
            corners[activePoint].y = pos.y;
            drawOverlay();
        }
    }

    function handleEnd() {
        isDragging = false;
        activePoint = null;
    }

    // --- Rotate Functions ---
    function rotateImage(degree) {
        var offCanvas = document.createElement('canvas');
        var offCtx = offCanvas.getContext('2d');
        
        // Swap Width/Height for 90 degree rotation
        offCanvas.width = originalImg.height;
        offCanvas.height = originalImg.width;
        
        offCtx.translate(offCanvas.width / 2, offCanvas.height / 2);
        offCtx.rotate(degree * Math.PI / 180);
        offCtx.drawImage(originalImg, -originalImg.width / 2, -originalImg.height / 2);
        
        // Update originalImg
        var rotatedUrl = offCanvas.toDataURL();
        originalImg.onload = function() {
            initScanner(); // Re-init with new image
        }
        originalImg.src = rotatedUrl;
    }

    $('#btnScanRotateLeft').click(function() { rotateImage(-90); });
    $('#btnScanRotateRight').click(function() { rotateImage(90); });

    // --- Reset Button ---
    $('#btnScanReset').click(function() {
        initScanner();
    });

    // --- Save / Extract Button ---
    $('#btnScanSave').click(function() {
        // Warp Image
        try {
             // 1. Get raw points relative to Original Image
             var scaleX = originalImg.width / canvasImage.width;
             var scaleY = originalImg.height / canvasImage.height;
             
             var tl = { x: corners[0].x * scaleX, y: corners[0].y * scaleY };
             var tr = { x: corners[1].x * scaleX, y: corners[1].y * scaleY };
             var br = { x: corners[2].x * scaleX, y: corners[2].y * scaleY };
             var bl = { x: corners[3].x * scaleX, y: corners[3].y * scaleY };
             
             // 2. Calculate dimensions of the crop area
             var widthTop = Math.hypot(tr.x - tl.x, tr.y - tl.y);
             var widthBottom = Math.hypot(br.x - bl.x, br.y - bl.y);
             var outputWidth = Math.max(widthTop, widthBottom);
             
             var heightLeft = Math.hypot(bl.x - tl.x, bl.y - tl.y);
             var heightRight = Math.hypot(br.x - tr.x, br.y - tr.y);
             var outputHeight = Math.max(heightLeft, heightRight);

             var extractPoints = {
                 topLeftCorner: tl,
                 topRightCorner: tr,
                 bottomRightCorner: br,
                 bottomLeftCorner: bl
             };
             
             // 3. Extract with dynamic dimensions
             var resultCanvas = scanner.extractPaper(originalImg, outputWidth, outputHeight, extractPoints);
             var base64 = resultCanvas.toDataURL('image/jpeg');
             
             if (window.handleScannerResult) {
                 window.handleScannerResult(base64);
             }
             
             scannerModal.modal('hide');

        } catch (e) {
            alert("Gagal memproses gambar: " + e.message);
        }
    });

});
</script>
