{% extends "base.html" %}

{% block body %}
<div x-data="oraEditor()" x-init="init()" class="min-h-screen pb-4">

    <!-- Fixed Header (mobile only) -->
    <header class="lg:hidden fixed top-0 left-0 right-0 z-[60] bg-gray-900 border-b border-gray-700 px-4 py-2">
        <div class="flex items-center justify-between max-w-full mx-auto">
            <!-- Open Dock button (top left) -->
            <button 
                x-show="oraPath"
                @click="showDock = true"
                :class="showDock ? 'bg-blue-600' : 'bg-gray-700 hover:bg-gray-600'"
                class="px-3 py-2 rounded min-h-[2.5rem] touch-manipulation transition"
                title="Open Dock"
            >📋</button>
            
            <!-- Spacer when dock button is hidden -->
            <div x-show="!oraPath" class="w-[3.75rem]"></div>
            
            <!-- Hamburger menu button (top right) -->
            <button 
                @click="showMenu = true"
                class="bg-gray-700 hover:bg-gray-600 px-3 py-2 rounded min-h-[2.5rem] touch-manipulation"
                title="Menu"
            >☰</button>
        </div>
    </header>

    <!-- Mobile hamburger dropdown menu (outside headers so it's visible) -->
    <div x-show="showMenu" x-transition class="lg:hidden fixed inset-0 z-[70]">
        <div @click="showMenu = false" class="absolute inset-0 bg-black opacity-50"></div>
        <div class="absolute top-12 right-0 bottom-0 w-full max-w-sm bg-gray-800 p-4 space-y-3 border-l border-gray-700 overflow-y-auto">
            <h3 class="font-bold text-lg mb-2">Menu</h3>
            
            <!-- File open controls -->
            <div class="space-y-2">
                <input 
                    type="text" 
                    x-model="filePath" 
                    placeholder="Path (e.g., scenes/kq4_010/pic.png)"
                    class="w-full bg-gray-700 border border-gray-600 rounded px-3 py-2 text-white focus:border-blue-500 outline-none"
                    @keydown.enter="openFile()"
                >
                <button 
                    @click="openBrowseModal(); showMenu = false;"
                    class="w-full bg-gray-600 hover:bg-gray-500 px-3 py-2 rounded transition min-h-[2.5rem] touch-manipulation"
                >
                    📁 Browse Files
                </button>
                <button 
                    @click="openFile(); showMenu = false;"
                    :disabled="!filePath || isLoading"
                    class="w-full bg-blue-600 hover:bg-blue-700 disabled:bg-gray-600 px-4 py-2 rounded transition flex items-center justify-center gap-2 min-h-[2.5rem] touch-manipulation"
                >
                    <span x-show="isLoading" class="animate-spin rounded-full h-4 w-4 border-t-2 border-b-2 border-white"></span>
                    <span x-text="isLoading ? 'Opening...' : 'Open File'"></span>
                </button>
            </div>
            
            <!-- Save -->
            <button 
                @click="saveCurrent(); showMenu = false;"
                :disabled="!oraPath || isLoading"
                class="w-full bg-green-600 hover:bg-green-700 disabled:bg-gray-600 px-4 py-2 rounded transition min-h-[2.5rem] touch-manipulation"
            >Save</button>
            
            <!-- Krita (desktop only info) -->
            <button 
                @click="openInKrita(); showMenu = false;"
                :disabled="!oraPath || isExtracting"
                class="w-full bg-purple-600 hover:bg-purple-700 disabled:bg-gray-600 px-4 py-2 rounded transition min-h-[2.5rem] touch-manipulation flex items-center gap-2 justify-center"
            >
                Open in Krita (Desktop Only)
            </button>
            
            <hr class="border-gray-700">
            
            <!-- Settings -->
            <button @click="showSettings = true; showMenu = false;" class="w-full bg-gray-700 hover:bg-gray-600 px-4 py-2 rounded transition min-h-[2.5rem] touch-manipulation">⚙️ Settings</button>
        </div>
    </div>

    <!-- Desktop Header -->
    <header class="hidden lg:flex mb-4 items-center justify-between px-4">
        <!-- Desktop header controls -->
        <div class="hidden lg:flex flex-1 flex items-center gap-2">
            <input 
                type="text" 
                x-model="filePath" 
                placeholder="Path (e.g., scenes/kq4_010/pic.png)"
                class="flex-1 bg-gray-700 border border-gray-600 rounded px-3 py-2 text-white focus:border-blue-500 outline-none"
                @keydown.enter="openFile()"
            >
            <button 
                @click="openBrowseModal()"
                class="bg-gray-600 hover:bg-gray-500 px-3 py-2 rounded transition min-h-[2.5rem] touch-manipulation"
                title="Browse files"
            >
                📁 Browse
            </button>
            <button 
                @click="openFile()"
                :disabled="!filePath || isLoading"
                class="bg-blue-600 hover:bg-blue-700 disabled:bg-gray-600 px-4 py-2 rounded transition flex items-center justify-center gap-2 min-h-[2.5rem] touch-manipulation"
            >
                <span x-show="isLoading" class="animate-spin rounded-full h-4 w-4 border-t-2 border-b-2 border-white"></span>
                <span x-text="isLoading ? 'Opening...' : 'Open'"></span>
            </button>
        </div>
        
        <!-- Krita button (desktop only) -->
        <button 
            @click="openInKrita()"
            :disabled="!oraPath || isExtracting"
            class="hidden lg:flex bg-purple-600 hover:bg-purple-700 disabled:bg-gray-600 px-4 py-2 rounded transition min-h-[2.5rem] touch-manipulation items-center gap-2"
            title="Open in Krita (Review mode: full ORA; Add mode: base with polygon)"
        >
            Open in Krita
        </button>
        
        <!-- Save button (desktop only) -->
        <button 
            @click="saveCurrent()"
            :disabled="!oraPath || isLoading"
            class="hidden lg:flex bg-green-600 hover:bg-green-700 disabled:bg-gray-600 px-4 py-2 rounded transition min-h-[2.5rem] touch-manipulation items-center"
        >Save</button>
        
        <!-- Save notification (below fixed header on mobile) -->
        <div 
            x-show="saveNotification" 
            x-transition
            class="fixed lg:top-4 top-14 right-4 bg-green-600 text-white px-4 py-2 rounded shadow-lg z-[55]"
            x-text="saveNotification"
        ></div>

        <!-- Scale slider (desktop only - moved to dock on mobile) -->
        <div x-show="oraPath" class="hidden lg:flex items-center gap-2 bg-gray-800 rounded px-3 py-2 border border-gray-700 min-h-[2.5rem]">
            <span class="text-sm text-gray-300">Scale:</span>
            <input 
                type="range" 
                x-model.number="scale" 
                min="10" 
                max="100" 
                step="5"
                class="w-32 accent-blue-500"
            >
            <span class="text-sm text-gray-300 w-12" x-text="scale + '%'"></span>
        </div>

        <!-- Settings button (desktop only) -->
        <button @click="showSettings = true" class="hidden lg:flex bg-gray-700 hover:bg-gray-600 px-4 py-2 rounded transition min-h-[2.5rem] touch-manipulation items-center">⚙️</button>
    </header>

    <!-- Main content (after file loaded) -->
    <template x-if="oraPath">
    <div class="flex gap-4 relative pt-12 lg:pt-0 px-4 lg:px-0">
        
        <!-- SIDEBAR DOCK (scrollable on mobile) -->
        <aside 
            x-show="showDock"
            @click.away="!showMaskModal && !showBrowseModal && !showSettings && !showKritaModal && window.innerWidth < 1024 && (showDock = false)"
            :class="{
                'fixed inset-0 z-40 bg-gray-800 w-full overflow-y-auto': window.innerWidth < 1024,
            }"
            class="lg:block lg:w-72 lg:flex-shrink-0 lg:static lg:inset-auto transition-all duration-300"
        >
            {% include "components/sidebar.html" %}
        </aside>

        <!-- MAIN CANVAS AREA -->
        <main class="flex-1 bg-gray-800 rounded-lg border border-gray-700 p-4 relative overflow-auto flex items-start justify-start min-h-[calc(100vh-12rem)] lg:min-h-[600px] lg:items-center lg:justify-center">
            
            <!-- Loading indicator -->
            <div x-show="isLoading && !error" class="flex items-center justify-center h-full absolute inset-0 z-10">
                <div class="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-blue-500"></div>
            </div>
            
            <!-- Error message -->
            <div x-show="error" class="text-red-400 text-center mt-8 absolute inset-0 z-10 flex items-center justify-center p-4" x-text="error"></div>
            
            <!-- Image container with centered scaling -->
            <div 
                id="imageContainer" 
                class="relative shadow-lg"
                :style="`width: ${scaledWidth}px; height: ${scaledHeight}px;`">
                
                <!-- Layer images stacked -->
                <div class="relative w-full h-full">
                    <template x-for="layer in layers" :key="'layer-' + layer.name">
                        <div x-show="layer.visible" class="absolute inset-0 w-full h-full">
                            <img 
                                :src="'/api/image/layer/' + encodeURIComponent(layer.name) + '?ora_path=' + encodeURIComponent(oraPath)"
                                class="absolute inset-0 w-full h-full object-contain pointer-events-none"
                            >
                        </div>
                    </template>
                    
                    <!-- SAM Include points (green) -->
                    <template x-if="mode === 'add' && isSamMode">
                        <template x-for="(point, idx) in samIncludePoints" :key="'sam-include-' + idx">
                            <div 
                                class="absolute w-5 h-5 bg-green-500 border-2 border-white rounded-full cursor-move z-20 flex items-center justify-center text-xs font-bold text-white"
                                style="transform: translate(-50%, -50%);"
                                :style="`left: ${point.x * 100}%; top: ${point.y * 100}%`"
                                @contextmenu.prevent="removeSamPoint('include', idx)"
                                x-text="idx + 1"
                            ></div>
                        </template>
                    </template>
                    
                    <!-- SAM Exclude points (red) -->
                    <template x-if="mode === 'add' && isSamMode">
                        <template x-for="(point, idx) in samExcludePoints" :key="'sam-exclude-' + idx">
                            <div 
                                class="absolute w-5 h-5 bg-red-500 border-2 border-white rounded-full cursor-move z-20 flex items-center justify-center text-xs font-bold text-white"
                                style="transform: translate(-50%, -50%);"
                                :style="`left: ${point.x * 100}%; top: ${point.y * 100}%`"
                                @contextmenu.prevent="removeSamPoint('exclude', idx)"
                                x-text="'X'"
                            ></div>
                        </template>
                    </template>
                    
                    <!-- Polygon points markers (draggable) - shown in add mode -->
                    <template x-if="mode === 'add' && polygonPoints.length > 0">
                        <template x-for="(point, idx) in polygonPoints" :key="'point-' + idx">
                            <div 
                                class="absolute w-4 h-4 bg-white border-2 border-red-500 rounded-full cursor-move z-10"
                                style="transform: translate(-50%, -50%);"
                                :style="`left: ${point.x * 100}%; top: ${point.y * 100}%`"
                                @mousedown="startDragPoint($event, idx)"
                                @touchstart.prevent="startDragPoint($event, idx)"
                            ></div>
                        </template>
                    </template>
                    
                    <!-- Polygon overlay after drawing -->
                    <img 
                        x-show="!isDrawing && polygonPreviewUrl" 
                        :src="polygonPreviewUrl" 
                        class="absolute inset-0 w-full h-full object-contain pointer-events-none"
                        alt="Polygon overlay"
                    >
                    
                    <!-- Drawing canvas (only when actively drawing) -->
                    <!-- Canvas is sized dynamically to match actual rendered container dimensions -->
                    <canvas
                        id="polygonCanvas"
                        x-show="isDrawing"
                        class="absolute inset-0 cursor-crosshair pointer-events-auto border-2 border-dashed border-blue-500 opacity-90"
                    ></canvas>
                    
                    <!-- SAM click canvas -->
                    <div 
                        x-show="isSamMode"
                        id="samCanvas"
                        class="absolute inset-0 cursor-crosshair z-10"
                        @click="handleSamClick($event)"
                        @contextmenu.prevent="handleSamRightClick($event)"
                    ></div>

                </div>

            </div>
            
            <!-- Mode-specific instructions -->
            <div x-show="isSamMode" class="absolute bottom-4 left-4 right-4 text-xs lg:text-sm text-gray-400 bg-gray-900 bg-opacity-75 px-3 py-2 rounded">
                Left-click to add include points (green). Right-click to add exclude points (red). Right-click on point to remove.
            </div>
            <div x-show="isDrawing" class="absolute bottom-4 left-4 right-4 text-xs lg:text-sm text-gray-400 bg-gray-900 bg-opacity-75 px-3 py-2 rounded">
                Click to add points. Drag points to adjust. Double-click or Enter to finish, Escape to cancel.
            </div>
            <div x-show="mode === 'add' && !isDrawing && polygonPoints.length >= 3" class="absolute bottom-4 left-4 right-4 text-xs lg:text-sm text-gray-400 bg-gray-900 bg-opacity-75 px-3 py-2 rounded">
                Drag points to adjust polygon, then extract mask or open in Krita.
            </div>
            <div x-show="mode === 'add' && !isDrawing && !polygonPreviewUrl && polygonPoints.length < 3 && !isSamMode" class="absolute bottom-4 left-4 right-4 text-xs lg:text-sm text-gray-400 bg-gray-900 bg-opacity-75 px-3 py-2 rounded">
                Use SAM rough mask or draw a polygon, then extract mask.
            </div>
        </main>
    </div>
    </template>

    <!-- No file loaded message -->
    <div x-show="!oraPath && !isLoading && !error" class="text-gray-400 text-center mt-20">
        <p class="text-xl">Open a PNG or ORA file to start editing</p>
    </div>

    <!-- Modals -->
    {% include "modals/browse.html" %}
    {% include "modals/settings.html" %}
    {% include "modals/mask_preview.html" %}
    {% include "modals/krita.html" %}

</div>
{% endblock %}

{% block scripts %}
<!-- Alpine.js data object -->
<script>
function oraEditor() {
    return {
        filePath: '',
        oraPath: '',
        layers: [],
        
        imageWidth: 800,
        imageHeight: 600,
        
        scale: 25,
        
        showMenu: false,
        showDock: true,
        previousScale: 25,  // Remember scale when switching modes
        
        mode: 'review',
        
        selectedLayer: null,
        
        entityName: '',
        
        isDrawing: false,
        polygonPoints: [],
        polygonColor: '#FF0000',
        polygonWidth: 2,
        polygonPreviewUrl: null,
        
         isSamMode: false,
          samIncludePoints: [],
          samExcludePoints: [],
          isSamGenerating: false,
          roughMaskPath: null,
          roughMaskUrl: null,
          denoiseStrength: 80,
          roughMaskThumbnailScale: 25,
        
        maskSubject: '',
        usePolygonHint: true,
        maskCount: 3,
        isExtracting: false,
        maskViewMode: 'with-bg',
        showMaskModal: false,
        tempMaskPath: null,
        tempMaskUrl: null,
        tempMaskPaths: [],
        currentMaskIndex: 0,
        lastError: '',
        
        showSettings: false,
        comfyUrl: localStorage.getItem('ora_comfy_url') || '127.0.0.1:8188',
        saveNotification: null,
        
        showKritaModal: false,
        kritaTempPath: null,
        kritaPathCopied: false,
        
        showBrowseModal: false,
        browsePath: '',
        browseDirectories: [],
        browseFiles: [],
        browseSelectedPath: null,
        
        isLoading: false,
        error: '',
        
        get scaledWidth() {
            return this.imageWidth * (this.scale / 100);
        },
        
        get scaledHeight() {
            return this.imageHeight * (this.scale / 100);
        },

        init() {
            console.log('ORA Editor initialized');
            this.setupKeyHandlers();
            this.$watch('scale', (newScale) => {
                this.roughMaskThumbnailScale = newScale;
            });
            // Close dock when exiting add mode on mobile
            this.$watch('mode', (newMode) => {
                if (newMode === 'review' && window.innerWidth < 1024) {
                    this.showDock = true;
                }
            });
        },

        setupKeyHandlers() {
            document.addEventListener('keydown', (e) => {
                if (e.key === 'Escape' && this.isDrawing) this.clearPolygon();
                if (e.key === 'Enter' && this.isDrawing && this.polygonPoints.length >= 3) this.finishDrawing();
            });
        },


        async openBrowseModal() {
            this.browsePath = '';
            this.browseSelectedPath = null;
            await this.loadBrowseDirectory('');
            this.showBrowseModal = true;
        },
        
        closeBrowseModal() {
            this.showBrowseModal = false;
        },
        
        async loadBrowseDirectory(path) {
            try {
                const response = await fetch('/api/browse?path=' + encodeURIComponent(path));
                const data = await response.json();
                
                if (data.success) {
                    this.browsePath = data.current_path;
                    this.browseDirectories = data.directories;
                    this.browseFiles = data.files;
                } else {
                    console.error('Browse error:', data.error);
                }
            } catch (e) {
                console.error('Browse error:', e);
            }
        },
        
        navigateBrowseDirectory(path) {
            this.browseSelectedPath = null;
            this.loadBrowseDirectory(path);
        },
        
        navigateBrowseParent() {
            const parent = this.browsePath.split('/').slice(0, -1).join('/');
            this.browseSelectedPath = null;
            this.loadBrowseDirectory(parent);
        },
        
        selectBrowseFile(file) {
            this.browseSelectedPath = file.path;
        },
        
        openBrowseFile(file) {
            this.filePath = file.path;
            this.showBrowseModal = false;
            this.openFile();
        },
        
        openSelectedFile() {
            if (this.browseSelectedPath) {
                this.filePath = this.browseSelectedPath;
                this.showBrowseModal = false;
                this.openFile();
            }
        },


        async openFile() {
            if (!this.filePath || this.isLoading) return;
            
            console.log('[ORA EDITOR] Opening file:', this.filePath);
            this.isLoading = true;
            this.error = '';
            
            try {
                const response = await fetch('/api/open', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ path: this.filePath })
                });
                
                const data = await response.json();
                
                console.log('[ORA EDITOR] File opened:', data);
                
                if (!data.success) throw new Error(data.error || 'Failed to open file');
                
                this.oraPath = data.ora_path;
                this.layers = data.layers.map(layer => ({
                    ...layer,
                    visible: true
                }));
                this.imageWidth = data.width;
                this.imageHeight = data.height;
                this.mode = 'review';
                this.clearPolygon();
            } catch (e) {
                console.error('[ORA EDITOR] Error opening file:', e);
                this.error = e.message;
            } finally {
                this.isLoading = false;
            }
        },

        async saveCurrent() {
            if (!this.oraPath) return;
            
            let savePath = this.oraPath;
            
            const response = await fetch('/api/save', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ ora_path: savePath })
            });
            
            const data = await response.json();
            if (data.success) {
                this.saveNotification = 'Saved to ' + savePath;
                setTimeout(() => { this.saveNotification = null; }, 3000);
            } else {
                alert('Error saving: ' + data.error);
            }
        },


        enterAddMode() {
            console.log('[ORA EDITOR] Entering add masked element mode');
            this.previousScale = this.scale;  // Save current scale
            this.mode = 'add';
            this.entityName = '';
            this.maskSubject = '';
            this.clearPolygon();
            this.clearSamPoints();
            this.scale = 100;
        },

        exitAddMode() {
            console.log('[ORA EDITOR] Exiting add masked element mode');
            this.mode = 'review';
            this.scale = this.previousScale;  // Restore previous scale
            this.isDrawing = false;
            this.polygonPoints = [];
            this.polygonPreviewUrl = null;
            this.isSamMode = false;
            this.samIncludePoints = [];
            this.samExcludePoints = [];
            this.roughMaskPath = null;
            this.roughMaskUrl = null;
            const canvas = document.getElementById('polygonCanvas');
            if (canvas) {
                canvas.style.display = 'none';
            }
        },

        async cancelAddMode() {
            if (this.isDrawing) {
                this.clearPolygon();
            } else if (this.isSamMode) {
                this.isSamMode = false;
            } else {
                this.exitAddMode();
            }
        },


        async toggleVisibility(layerName, visible) {
            const idx = this.layers.findIndex(l => l.name === layerName);
            if (idx >= 0) {
                this.layers[idx].visible = visible;
            }
            
            await fetch('/api/layer/visibility', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ 
                    ora_path: this.oraPath,
                    layer_name: layerName,
                    visible: visible 
                })
            });
        },

        async renameLayer() {
            const oldName = this.selectedLayer;
            const newName = prompt('New layer name:', this.selectedLayer);
            if (!newName || newName === oldName) return;
            
            const layer = this.layers.find(l => l.name === oldName);
            if (layer) layer.name = newName;
            this.selectedLayer = newName;
            
            await fetch('/api/layer/rename', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ 
                    ora_path: this.oraPath,
                    old_name: oldName,
                    new_name: newName 
                })
            });
        },

        async deleteLayer() {
            const layerToDelete = this.selectedLayer;
            if (!confirm(`Delete layer "${layerToDelete}"?`)) return;
            
            const idx = this.layers.findIndex(l => l.name === layerToDelete);
            if (idx > -1) this.layers.splice(idx, 1);
            this.selectedLayer = null;
            
            await fetch('/api/layer/delete', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ 
                    ora_path: this.oraPath,
                    layer_name: layerToDelete 
                })
            });
        },

        async reorderLayer(direction) {
            if (!this.selectedLayer) return;
            
            const idx = this.layers.findIndex(l => l.name === this.selectedLayer);
            if (idx < 0) return;
            
            const newIdx = direction === 'up' ? idx - 1 : idx + 1;
            if (newIdx < 0 || newIdx >= this.layers.length) return;
            
            const layerName = this.selectedLayer;
            [this.layers[idx], this.layers[newIdx]] = [this.layers[newIdx], this.layers[idx]];
            
            await fetch('/api/layer/reorder', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ 
                    ora_path: this.oraPath,
                    layer_name: layerName,
                    direction: direction
                })
            });
        },


        startDrawing() {
            console.log('[ORA EDITOR] Starting polygon drawing mode');
            this.isDrawing = true;
            this.polygonPoints = [];
            canvasDoubleClickPending = false;
            this.polygonPreviewUrl = null;
            
            setTimeout(() => {
                this.setupCanvas();
                const canvas = document.getElementById('polygonCanvas');
                if (canvas) {
                    canvas.style.display = 'block';
                }
            }, 50);
        },

        setupCanvas() {
            const canvas = document.getElementById('polygonCanvas');
            const container = document.getElementById('imageContainer');
            if (!canvas || !container) return;
            
            // Match canvas to ACTUAL RENDERED container dimensions
            // The container may be constrained by viewport/CSS even with explicit pixel width
            const rect = container.getBoundingClientRect();
            canvas.width = rect.width;
            canvas.height = rect.height;
            
            console.log('[SETUP CANVAS]', {
                scaledWidth: this.scaledWidth,
                scaledHeight: this.scaledHeight,
                actualWidth: rect.width,
                actualHeight: rect.height,
                constrained: rect.width !== this.scaledWidth || rect.height !== this.scaledHeight
            });
        },

        addPolygonPoint(x, y) {
            if (!this.isDrawing) return;
            
            console.log('[ADD POINT] Before clamp:', {x, y});
            
            x = Math.max(-0.1, Math.min(1.1, x));
            y = Math.max(-0.1, Math.min(1.1, y));
            
            console.log('[ADD POINT] After clamp:', {x, y}, 'Total points:', this.polygonPoints.length + 1);
            
            this.polygonPoints.push({ x, y });
            this.drawPolygonOnCanvas();
        },

        startDragPoint(e, idx) {
            e.preventDefault();
            e.stopPropagation();
            const container = document.getElementById('imageContainer');
            if (!container) return;
            
            const moveHandler = (moveEvent) => {
                const rect = container.getBoundingClientRect();
                let x, y;
                
                if (moveEvent.touches) {
                    x = (moveEvent.touches[0].clientX - rect.left) / rect.width;
                    y = (moveEvent.touches[0].clientY - rect.top) / rect.height;
                } else {
                    x = (moveEvent.clientX - rect.left) / rect.width;
                    y = (moveEvent.clientY - rect.top) / rect.height;
                }
                
                x = Math.max(-0.1, Math.min(1.1, x));
                y = Math.max(-0.1, Math.min(1.1, y));
                
                this.polygonPoints[idx] = { x, y };
                this.drawPolygonOnCanvas();
            };
            
            const upHandler = () => {
                document.removeEventListener('mousemove', moveHandler);
                document.removeEventListener('mouseup', upHandler);
                document.removeEventListener('touchmove', moveHandler);
                document.removeEventListener('touchend', upHandler);
                
                if (this.polygonPoints.length >= 3) {
                    this.updatePolygonPreview();
                }
            };
            
            document.addEventListener('mousemove', moveHandler);
            document.addEventListener('mouseup', upHandler);
            document.addEventListener('touchmove', moveHandler);
            document.addEventListener('touchend', upHandler);
        },

        drawPolygonOnCanvas() {
            const canvas = document.getElementById('polygonCanvas');
            const container = document.getElementById('imageContainer');
            if (!canvas || this.polygonPoints.length < 2) return;
            
            const ctx = canvas.getContext('2d');
            if (!ctx) return;
            
            // Check if canvas dimensions match actual container size
            // Container may be constrained by viewport
            if (container) {
                const rect = container.getBoundingClientRect();
                if (canvas.width !== rect.width || canvas.height !== rect.height) {
                    console.log('[DRAW] Resizing canvas to match container:', rect.width, 'x', rect.height);
                    canvas.width = rect.width;
                    canvas.height = rect.height;
                }
            }
            
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            
            ctx.beginPath();
            ctx.strokeStyle = this.polygonColor;
            ctx.lineWidth = this.polygonWidth;
            ctx.lineCap = 'round';
            ctx.lineJoin = 'round';
            
            const startPoint = this.polygonPoints[0];
            ctx.moveTo(startPoint.x * canvas.width, startPoint.y * canvas.height);
            
            for (let i = 1; i < this.polygonPoints.length; i++) {
                const point = this.polygonPoints[i];
                ctx.lineTo(point.x * canvas.width, point.y * canvas.height);
            }
            
            if (this.polygonPoints.length >= 3) {
                ctx.closePath();
            }
            
            ctx.stroke();
            
            ctx.fillStyle = '#FFFFFF';
            for (const point of this.polygonPoints) {
                const px = point.x * canvas.width;
                const py = point.y * canvas.height;
                
                ctx.beginPath();
                ctx.arc(px, py, 6, 0, Math.PI * 2);
                ctx.fill();
                
                ctx.beginPath();
                ctx.strokeStyle = this.polygonColor;
                ctx.lineWidth = 2;
                ctx.arc(px, py, 6, 0, Math.PI * 2);
                ctx.stroke();
            }
        },

        async updatePolygonPreview() {
            console.log('[UPDATE] Updating preview with', this.polygonPoints.length, 'points');
            if (!this.oraPath || this.polygonPoints.length < 3) return;
            
            const response = await fetch('/api/polygon', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({
                    ora_path: this.oraPath,
                    points: [...this.polygonPoints],
                    color: this.polygonColor,
                    width: this.polygonWidth
                })
            });
            
            if (response.ok) {
                const data = await response.json();
                this.polygonPreviewUrl = data.overlay_url + '&ts=' + Date.now();
            }
        },

        async finishDrawing() {
            console.log('[FINISH] finishDrawing called');
            if (this.polygonPoints.length >= 3) {
                await this.updatePolygonPreview();
                this.isDrawing = false;
                
                const canvas = document.getElementById('polygonCanvas');
                if (canvas) {
                    canvas.style.display = 'none';
                }
            } else {
                this.clearPolygon();
            }
        },

        clearPolygon() {
            this.isDrawing = false;
            this.polygonPoints = [];
            this.polygonPreviewUrl = null;
            
            const canvas = document.getElementById('polygonCanvas');
            if (canvas) {
                canvas.style.display = 'none';
                const ctx = canvas.getContext('2d');
                if (ctx) {
                    ctx.clearRect(0, 0, canvas.width, canvas.height);
                }
            }
            
            if (this.oraPath) {
                fetch('/api/polygon/clear', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ ora_path: this.oraPath })
                });
            }
        },


        startSamMode() {
            console.log('[ORA EDITOR] Starting SAM mode');
            this.isSamMode = true;
            this.samIncludePoints = [];
            this.samExcludePoints = [];
            this.roughMaskPath = null;
            this.roughMaskUrl = null;
        },
        
        clearSamPoints() {
            this.samIncludePoints = [];
            this.samExcludePoints = [];
            this.roughMaskPath = null;
            this.roughMaskUrl = null;
        },
        
        handleSamClick(e) {
            if (!this.isSamMode) return;
            
            const container = document.getElementById('imageContainer');
            if (!container) return;
            
            const rect = container.getBoundingClientRect();
            let x = (e.clientX - rect.left) / rect.width;
            let y = (e.clientY - rect.top) / rect.height;
            
            x = Math.max(0, Math.min(1, x));
            y = Math.max(0, Math.min(1, y));
            
            this.samIncludePoints.push({ x, y });
            console.log('[SAM] Added include point:', x, y);
        },
        
        handleSamRightClick(e) {
            if (!this.isSamMode) return;
            e.preventDefault();
            
            const container = document.getElementById('imageContainer');
            if (!container) return;
            
            const rect = container.getBoundingClientRect();
            let x = (e.clientX - rect.left) / rect.width;
            let y = (e.clientY - rect.top) / rect.height;
            
            x = Math.max(0, Math.min(1, x));
            y = Math.max(0, Math.min(1, y));
            
            this.samExcludePoints.push({ x, y });
            console.log('[SAM] Added exclude point:', x, y);
        },
        
        removeSamPoint(type, idx) {
            if (type === 'include') {
                this.samIncludePoints.splice(idx, 1);
            } else {
                this.samExcludePoints.splice(idx, 1);
            }
        },
        
        async generateSamMask() {
            if (this.samIncludePoints.length === 0 || !this.oraPath) return;
            
            console.log('[ORA EDITOR] Generating SAM mask with', this.samIncludePoints.length, 'include points');
            this.isSamGenerating = true;
            
            try {
                const response = await fetch('/api/sam/generate', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({
                        ora_path: this.oraPath,
                        include_points: this.samIncludePoints,
                        exclude_points: this.samExcludePoints,
                        comfy_url: this.comfyUrl
                    })
                });
                
                const data = await response.json();
                
                console.log('[ORA EDITOR] SAM response:', data);
                
               if (!data.success) throw new Error(data.error || 'Failed');
                 
                this.roughMaskPath = data.mask_path;
                this.roughMaskUrl = data.mask_url;
                this.roughMaskThumbnailScale = this.scale;
                this.isSamMode = false;
            } catch (e) {
                console.error('[ORA EDITOR] Error generating SAM mask:', e);
                this.lastError = e.message;
            } finally {
                this.isSamGenerating = false;
            }
        },
        
        discardRoughMask() {
            this.roughMaskPath = null;
            this.roughMaskUrl = null;
            this.samIncludePoints = [];
            this.samExcludePoints = [];
        },
        
        openRoughMaskInNewWindow() {
            if (!this.roughMaskUrl) return;
            
            const win = window.open('', '_blank');
            const scale = this.scale / 100;
            const scaledWidth = this.imageWidth * scale;
            const scaledHeight = this.imageHeight * scale;
            
            win.document.write(`<!DOCTYPE html>
<html>
<head>
    <title>Rough Mask Preview</title>
    <style>
        body { 
            margin: 0; 
            padding: 20px; 
            background: #1f2937; 
            color: white;
            display: flex;
            flex-direction: column;
            align-items: center;
            min-height: 100vh;
        }
        .info { margin-bottom: 10px; text-align: center; }
        .container {
            transform-origin: top left;
        }
        img { 
            display: block;
            opacity: 0.7;
            box-shadow: 0 4px 6px rgba(0,0,0,0.3);
        }
    </style>
</head>
<body>
    <div class="info">
        <h2>Rough Mask Preview</h2>
        <p>Original: ${this.imageWidth}x${this.imageHeight}px | Scale: ${(scale * 100).toFixed(0)}%</p>
    </div>
    <div class="container" style="transform: scale(${scale});">
        <img src="${this.roughMaskUrl}" alt="Rough Mask" style="width: ${this.imageWidth}px; height: ${this.imageHeight}px;">
    </div>
</body>
</html>`);
            win.document.close();
        },


        async extractMask() {
            if (!this.maskSubject.trim()) return;
            
            console.log('[ORA EDITOR] Extracting', this.maskCount, 'masks for:', this.maskSubject);
            this.isExtracting = true;
            this.lastError = '';
            
            const requestBody = {
                subject: this.maskSubject,
                use_polygon: this.usePolygonHint && this.polygonPoints.length >= 3,
                ora_path: this.oraPath,
                comfy_url: this.comfyUrl,
                count: this.maskCount,
                denoise_strength: this.denoiseStrength / 100
            };
            
            if (this.roughMaskPath) {
                requestBody.start_mask_path = this.roughMaskPath;
                console.log('[ORA EDITOR] Using rough mask as starting point:', this.roughMaskPath);
            }
            
            try {
                const response = await fetch('/api/mask/extract', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify(requestBody)
                });
                
                const data = await response.json();
                
                console.log('[ORA EDITOR] Mask extraction response:', data);
                
                if (!data.success) throw new Error(data.error || 'Failed');
                
                this.tempMaskPaths = data.mask_paths || [data.mask_path];
                this.currentMaskIndex = 0;
                this.tempMaskPath = this.tempMaskPaths[0];
                this.tempMaskUrl = data.mask_urls?.[0] || '/api/file/mask?path=' + encodeURIComponent(this.tempMaskPath);
                
                // Clear rough mask after successful extraction
                this.roughMaskPath = null;
                this.roughMaskUrl = null;
                this.isSamMode = false;
                
                this.showMaskModal = true;
            } catch (e) {
                console.error('[ORA EDITOR] Error extracting mask:', e);
                this.lastError = e.message;
            } finally {
                this.isExtracting = false;
            }
        },
        
        get currentMaskPath() {
            return this.tempMaskPaths[this.currentMaskIndex] || null;
        },

        previousMask() {
            if (this.currentMaskIndex > 0) {
                this.currentMaskIndex--;
                this.tempMaskPath = this.tempMaskPaths[this.currentMaskIndex];
            }
        },

        nextMask() {
            if (this.currentMaskIndex < this.tempMaskPaths.length - 1) {
                this.currentMaskIndex++;
                this.tempMaskPath = this.tempMaskPaths[this.currentMaskIndex];
            }
        },

        rerollMasks() {
            this.extractMask();
        },

        async useCurrentMask() {
            if (!this.currentMaskPath) return;
            
            let finalEntityName = this.entityName || 'element';
            const existingLayers = this.layers.filter(l => l.name.startsWith(finalEntityName + '_'));
            let counter = 0;
            while (existingLayers.some(l => l.name === `${finalEntityName}_${counter}`)) {
                counter++;
            }
            finalEntityName = `${finalEntityName}_${counter}`;
            
            console.log('[ORA EDITOR] Adding layer:', finalEntityName, 'with mask:', this.currentMaskPath);
             
            await fetch('/api/layer/add', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({
                    ora_path: this.oraPath,
                    entity_name: finalEntityName,
                    mask_path: this.currentMaskPath
                })
            });
             
            const response = await fetch('/api/layers?ora_path=' + encodeURIComponent(this.oraPath));
            const data = await response.json();
            if (data.success) {
                this.layers = data.layers.map(layer => ({
                    ...layer,
                    visible: true
                }));
            }
            	
            this.closeMaskModal();
            this.exitAddMode();
        },

        closeMaskModal() {
            this.showMaskModal = false;
            this.tempMaskPath = null;
            this.tempMaskUrl = null;
            this.tempMaskPaths = [];
            this.currentMaskIndex = 0;
            
            // Clear SAM mode when mask preview dismissed (user decided on something else or cancelled)
            this.isSamMode = false;
        },


        async openInKrita() {
            if (!this.oraPath) return;
            
            let requestBody;
            
            if (this.mode === 'review') {
                requestBody = {
                    ora_path: this.oraPath,
                    open_full_ora: true
                };
            } else {
                requestBody = {
                    ora_path: this.oraPath,
                    open_base_with_polygon: true,
                    points: this.polygonPoints,
                    color: this.polygonColor,
                    width: this.polygonWidth
                };
            }
             
            const response = await fetch('/api/krita/open', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify(requestBody)
            });
             
            const data = await response.json();
            if (data.success) {
                this.kritaTempPath = data.temp_path;
                this.showKritaModal = true;
            } else {
                alert('Error: ' + data.error);
            }
        },

        copyKritaPath() {
            if (this.kritaTempPath) {
                navigator.clipboard.writeText(this.kritaTempPath);
                this.kritaPathCopied = true;
                setTimeout(() => { this.kritaPathCopied = false; }, 2000);
            }
        },

        closeKritaModal() {
            this.showKritaModal = false;
            this.kritaTempPath = null;
            this.kritaPathCopied = false;
        },


        saveSettings() {
            localStorage.setItem('ora_comfy_url', this.comfyUrl);
            this.showSettings = false;
        }
    };
}
</script>

<!-- Custom JS for canvas click handling -->
<script>
let canvasDoubleClickPending = false;

document.addEventListener('alpine:init', () => {
    const observer = new MutationObserver(() => {
        const canvas = document.getElementById('polygonCanvas');
        if (canvas && !canvas.hasAttribute('data-handlers-setup')) {
            canvas.setAttribute('data-handlers-setup', 'true');
            
            canvas.addEventListener('click', (e) => {
                if (canvasDoubleClickPending) return;
                
                const container = document.getElementById('imageContainer');
                if (!container) return;
                
                const rect = container.getBoundingClientRect();
                let x = (e.clientX - rect.left) / rect.width;
                let y = (e.clientY - rect.top) / rect.height;
                
                // Debug logging
                console.log('[CANVAS CLICK]', {
                    clientX: e.clientX, clientY: e.clientY,
                    rectLeft: rect.left, rectTop: rect.top,
                    rectWidth: rect.width, rectHeight: rect.height,
                    calculatedX: x, calculatedY: y,
                    canvasWidth: canvas.width, canvasHeight: canvas.height
                });
                
                x = Math.max(-0.1, Math.min(1.1, x));
                y = Math.max(-0.1, Math.min(1.1, y));
                
                const alpineEl = container.closest('[x-data]');
                if (!alpineEl) return;
                
                const store = Alpine.$data(alpineEl);
                if (store && store.isDrawing) {
                    store.addPolygonPoint(x, y);
                }
            });
            
            canvas.addEventListener('dblclick', (e) => {
                e.preventDefault();
                canvasDoubleClickPending = true;
                
                const container = document.getElementById('imageContainer');
                if (!container) return;
                
                const alpineEl = container.closest('[x-data]');
                if (!alpineEl) return;
                
                const store = Alpine.$data(alpineEl);
                if (store && store.isDrawing && store.polygonPoints.length >= 3) {
                    store.finishDrawing();
                }
            });
            
            setTimeout(() => { canvasDoubleClickPending = false; }, 200);
        }
    });
    
    observer.observe(document.body, { childList: true, subtree: true });
});
</script>
{% endblock %}