/**
 * Cut Drawing Module
 * Handles polygon drawing functionality for cut creation
 */

class CutDrawing {
    constructor(map) {
        this.map = map;
        this.vertices = [];
        this.markers = [];
        this.polyline = null;
        this.polygon = null; // Add polygon preview
        this.finalPolygon = null; // Final polygon after finishing
        this.isDrawing = false;
        this.onFinishCallback = null;
        this.onCancelCallback = null;
        this.currentColor = '#3388ff';
        this.currentOpacity = 0.3;
    }
    
    startDrawing(onFinish, onCancel) {
        if (this.isDrawing) {
            this.cancelDrawing();
        }
        
        this.isDrawing = true;
        this.onFinishCallback = onFinish;
        this.onCancelCallback = onCancel;
        this.vertices = [];
        this.markers = [];
        
        this.map.getContainer().style.cursor = 'crosshair';
        this.map.on('click', this.onMapClick.bind(this));
        this.map.doubleClickZoom.disable();
        
        console.log('Cut drawing started - click to add points');
    }
    
    onMapClick(e) {
        if (!this.isDrawing) return;
        
        // Check if clicking on first vertex to close polygon
        if (this.vertices.length >= 3) {
            const firstVertex = this.vertices[0];
            const clickPoint = this.map.latLngToContainerPoint(e.latlng);
            const firstPoint = this.map.latLngToContainerPoint(firstVertex);
            const distance = Math.sqrt(
                Math.pow(clickPoint.x - firstPoint.x, 2) + 
                Math.pow(clickPoint.y - firstPoint.y, 2)
            );
            
            // If clicked within 15 pixels of first vertex, close the polygon
            if (distance < 15) {
                console.log('Closing polygon by clicking first vertex');
                this.finishDrawing();
                return;
            }
        }
        
        // Add vertex marker with special styling for first vertex
        const isFirstVertex = this.vertices.length === 0;
        const marker = L.marker(e.latlng, {
            icon: L.divIcon({
                className: 'cut-vertex-marker' + (isFirstVertex ? ' first-vertex' : ''),
                html: `<div class="vertex-point${isFirstVertex ? ' first' : ''}"></div>`,
                iconSize: [12, 12],
                iconAnchor: [6, 6]
            }),
            draggable: false
        }).addTo(this.map);
        
        // Add tooltip to first vertex after 3 points
        if (isFirstVertex) {
            marker.bindTooltip('Click to close polygon', {
                permanent: false,
                direction: 'top',
                offset: [0, -10]
            });
        }
        
        this.vertices.push(e.latlng);
        this.markers.push(marker);
        this.updatePolyline();
        
        // Show tooltip on first vertex when we have enough points
        if (this.vertices.length === 3 && this.markers[0]) {
            this.markers[0].openTooltip();
        }
        
        // Call update callback if available
        if (this.onUpdate) {
            this.onUpdate();
        }
        
        console.log(`Added vertex ${this.vertices.length} at`, e.latlng);
    }
    
    updatePolyline() {
        // Use stored color and opacity values
        const color = this.currentColor;
        const opacity = this.currentOpacity;

        if (this.polyline) {
            this.map.removeLayer(this.polyline);
        }

        if (this.polygon) {
            this.map.removeLayer(this.polygon);
            this.polygon = null;
        }

        if (this.vertices.length > 1) {
            // Show polyline for incomplete polygon
            this.polyline = L.polyline(this.vertices, {
                color: color,
                weight: 2,
                dashArray: '5, 5',
                opacity: 1.0 // Keep polyline stroke visible
            }).addTo(this.map);

            // Show preview polygon if we have 3+ vertices
            if (this.vertices.length >= 3) {
                this.polygon = L.polygon(this.vertices, {
                    color: color,
                    fillColor: color,
                    fillOpacity: opacity,
                    weight: 2,
                    opacity: 0.8,
                    dashArray: '5, 5'
                }).addTo(this.map);
                
                // Add cut-polygon class and force inline style
                if (this.polygon._path) {
                    this.polygon._path.classList.add('cut-polygon');
                    // Use setProperty with important flag for stronger override
                    this.polygon._path.style.setProperty('fill-opacity', opacity, 'important');
                    this.polygon._path.style.setProperty('fill', color, 'important');
                    console.log(`Created/updated polygon with opacity: ${opacity}`);
                }
                
                console.log('Created/updated polygon with opacity:', opacity);
            }
        }
    }
    
    finishDrawing() {
        console.log('finishDrawing() called');
        console.log('isDrawing:', this.isDrawing);
        console.log('vertices count:', this.vertices.length);
        
        if (!this.isDrawing) {
            console.log('Not in drawing mode, returning null');
            return null;
        }
        
        if (this.vertices.length < 3) {
            alert('A cut must have at least 3 points. Click more points or cancel drawing.');
            return null;
        }
        
        // Store vertices before cleanup
        const finalVertices = [...this.vertices];
        
        // Use stored color and opacity values
        const color = this.currentColor;
        const opacity = this.currentOpacity;
        
        // Create polygon from vertices
        const polygon = L.polygon(finalVertices, {
            color: color,
            fillColor: color,
            fillOpacity: opacity,
            weight: 2,
            opacity: 1.0 // Keep stroke visible
        });
        
        // Get GeoJSON and bounds
        const geojson = polygon.toGeoJSON().geometry; // Get just the geometry part
        const bounds = polygon.getBounds();
        
        // Clean up drawing elements but keep the final polygon
        this.cleanupDrawingElements();
        
        // Add the final polygon to the map
        this.finalPolygon = polygon.addTo(this.map);
        
        // Call finish callback with the data
        console.log('Calling finish callbacks...');
        const callbackData = {
            geojson: JSON.stringify(geojson),
            bounds: JSON.stringify([
                [bounds.getSouth(), bounds.getWest()],
                [bounds.getNorth(), bounds.getEast()]
            ]),
            vertexCount: finalVertices.length,
            polygon: this.finalPolygon
        };
        
        if (this.onFinishCallback) {
            console.log('Calling onFinishCallback');
            this.onFinishCallback(callbackData);
        } else {
            console.log('No onFinishCallback set');
        }
        
        // Also call the onFinish callback if set
        if (this.onFinish) {
            console.log('Calling onFinish');
            this.onFinish(callbackData);
        } else {
            console.log('No onFinish callback set');
        }
        
        console.log('Cut drawing finished with', finalVertices.length, 'vertices');
        return geojson;
    }
    
    cancelDrawing() {
        if (!this.isDrawing) return;
        
        console.log('Cut drawing cancelled');
        this.cleanup();
        
        if (this.onCancelCallback) {
            this.onCancelCallback();
        }
        
        // Also call the onCancel callback if set
        if (this.onCancel) {
            this.onCancel();
        }
    }
    
    undoLastVertex() {
        if (!this.isDrawing || this.vertices.length === 0) return;
        
        this.vertices.pop();
        const lastMarker = this.markers.pop();
        if (lastMarker) {
            this.map.removeLayer(lastMarker);
        }
        
        this.updatePolyline();
        
        // Call update callback if available
        if (this.onUpdate) {
            this.onUpdate();
        }
        
        console.log('Removed last vertex, remaining:', this.vertices.length);
    }
    
    clearVertices() {
        if (!this.isDrawing) return;
        
        this.markers.forEach(marker => {
            this.map.removeLayer(marker);
        });
        
        if (this.polyline) {
            this.map.removeLayer(this.polyline);
            this.polyline = null;
        }
        
        if (this.polygon) {
            this.map.removeLayer(this.polygon);
            this.polygon = null;
        }
        
        this.vertices = [];
        this.markers = [];
        
        // Call update callback if available
        if (this.onUpdate) {
            this.onUpdate();
        }
        
        console.log('Cleared all vertices');
    }
    
    cleanupDrawingElements() {
        // Remove drawing elements but preserve final polygon
        this.markers.forEach(marker => {
            this.map.removeLayer(marker);
        });
        
        if (this.polyline) {
            this.map.removeLayer(this.polyline);
        }
        
        if (this.polygon) {
            this.map.removeLayer(this.polygon);
        }
        
        this.map.getContainer().style.cursor = '';
        this.map.off('click', this.onMapClick);
        this.map.doubleClickZoom.enable();
        
        this.isDrawing = false;
        this.vertices = [];
        this.markers = [];
        this.polyline = null;
        this.polygon = null;
        this.onFinishCallback = null;
        this.onCancelCallback = null;
    }
    
    cleanup() {
        this.markers.forEach(marker => {
            this.map.removeLayer(marker);
        });
        
        if (this.polyline) {
            this.map.removeLayer(this.polyline);
        }
        
        if (this.polygon) {
            this.map.removeLayer(this.polygon);
        }
        
        if (this.finalPolygon) {
            this.map.removeLayer(this.finalPolygon);
        }
        
        this.map.getContainer().style.cursor = '';
        this.map.off('click', this.onMapClick);
        this.map.doubleClickZoom.enable();
        
        this.isDrawing = false;
        this.vertices = [];
        this.markers = [];
        this.polyline = null;
        this.polygon = null;
        this.finalPolygon = null;
        this.onFinishCallback = null;
        this.onCancelCallback = null;
    }
    
    getState() {
        return {
            isDrawing: this.isDrawing,
            vertexCount: this.vertices.length,
            canFinish: this.vertices.length >= 3
        };
    }

    // Add method to update current drawing style
    updateDrawingStyle(color, opacity) {
        this.currentColor = color;
        this.currentOpacity = opacity;
        
        console.log(`CutDrawing.updateDrawingStyle called with color: ${color}, opacity: ${opacity}`);
        
        // Update polyline color
        if (this.polyline) {
            this.polyline.setStyle({ color: color });
        }
        
        // Update polygon if it exists
        if (this.polygon) {
            this.polygon.setStyle({
                color: color,
                fillColor: color,
                fillOpacity: opacity,
                opacity: 0.8  // Border opacity
            });
            
            // Force inline style update and browser reflow
            if (this.polygon._path) {
                // Use setProperty with important flag for stronger override
                this.polygon._path.style.setProperty('fill-opacity', opacity, 'important');
                this.polygon._path.style.setProperty('fill', color, 'important');
                
                // Force multiple reflows to ensure update
                void this.polygon._path.offsetHeight;
                void this.polygon._path.offsetWidth;
                
                // Force repaint by temporarily changing a property
                const oldDisplay = this.polygon._path.style.display;
                this.polygon._path.style.display = 'none';
                void this.polygon._path.offsetHeight;
                this.polygon._path.style.display = oldDisplay;
            }
            
            // Also try Leaflet's internal redraw
            if (this.polygon._updatePath) {
                this.polygon._updatePath();
            }
            
            console.log(`Updated active drawing polygon with opacity: ${opacity}`);
        } else {
            // If no polygon exists but we have vertices, force a complete redraw
            console.log('No polygon exists, forcing complete redraw');
            this.forceRedraw();
        }
    }

    clearPreview() {
        // Clear any preview polygons but not the final polygon
        if (this.polygon) {
            this.map.removeLayer(this.polygon);
            this.polygon = null;
        }
        
        if (this.polyline && this.isDrawing) {
            this.map.removeLayer(this.polyline);
            this.polyline = null;
        }
    }

    // Force a complete redraw with current style settings
    forceRedraw() {
        if (this.vertices.length > 1) {
            console.log('Forcing complete redraw with vertices:', this.vertices.length);
            this.updatePolyline();
        }
    }
}

// Export the class if using modules, otherwise it's global
if (typeof module !== 'undefined' && module.exports) {
    module.exports = CutDrawing;
} else {
    window.CutDrawing = CutDrawing;
}
