/**
 * GIS 지도 컨트롤러
 */

import { getVesselCountColor, getTrackColor, calculateBounds } from '../utils/gis-utils.js';

export class GISMapController {
    constructor(containerId = 'mapContainer') {
        this.containerId = containerId;
        this.map = null;
        this.deckOverlay = null;
        this.layers = new Map();
        this.tooltipCallback = null;
    }

    /**
     * 지도 초기화
     */
    async init() {
        return new Promise((resolve) => {
            this.map = new maplibregl.Map({
                container: this.containerId,
                style: {
                    version: 8,
                    sources: {
                        'local-tiles': {
                            type: 'raster',
                            tiles: ['/api/tiles/world/{z}/{x}/{y}.webp'],
                            tileSize: 256,
                            attribution: 'Local Tile Server'
                        }
                    },
                    layers: [{
                        id: 'base-tiles',
                        type: 'raster',
                        source: 'local-tiles',
                        minzoom: 4,
                        maxzoom: 14
                    }]
                },
                center: [126.0, 35.0],
                zoom: 6
            });

            this.map.on('load', () => {
                this.initDeckOverlay();
                this.addNavigationControl();
                resolve();
            });
        });
    }

    /**
     * Deck.gl 오버레이 초기화
     */
    initDeckOverlay() {
        this.deckOverlay = new deck.MapboxOverlay({
            layers: [],
            getTooltip: this.getTooltip.bind(this)
        });
        
        this.map.addControl(this.deckOverlay);
    }

    /**
     * 네비게이션 컨트롤 추가
     */
    addNavigationControl() {
        this.map.addControl(new maplibregl.NavigationControl(), 'top-right');
    }

    /**
     * Haegu 레이어 업데이트
     */
    updateHaeguLayer(haegus, stats) {
        if (!haegus || haegus.length === 0) {
            this.layers.delete('haegu-layer');
            this.updateDeckLayers();
            return;
        }

        const layer = new deck.GeoJsonLayer({
            id: 'haegu-layer',
            data: {
                type: 'FeatureCollection',
                features: haegus.map(haegu => ({
                    type: 'Feature',
                    properties: {
                        haegu_no: haegu.haegu_no,
                        vessel_count: stats?.[haegu.haegu_no]?.vessel_count || 0,
                        total_distance: stats?.[haegu.haegu_no]?.total_distance || 0
                    },
                    geometry: JSON.parse(haegu.geom_json)
                }))
            },
            filled: true,
            stroked: true,
            getFillColor: d => getVesselCountColor(d.properties.vessel_count),
            getLineColor: [0, 100, 200, 255],
            getLineWidth: 2,
            lineWidthMinPixels: 1,
            pickable: true,
            autoHighlight: true,
            highlightColor: [255, 255, 0, 100],
            onClick: (info) => this.handleAreaClick('haegu', info),
            onRightClick: (info) => this.handleAreaRightClick('haegu', info)
        });
        
        this.layers.set('haegu-layer', layer);
        this.updateDeckLayers();
    }

    /**
     * Area 레이어 업데이트
     */
    updateAreaLayer(areas, stats) {
        if (!areas || areas.length === 0) {
            this.layers.delete('area-layer');
            this.updateDeckLayers();
            return;
        }

        const layer = new deck.GeoJsonLayer({
            id: 'area-layer',
            data: {
                type: 'FeatureCollection',
                features: areas.map(area => ({
                    type: 'Feature',
                    properties: {
                        area_id: area.area_id,
                        area_name: area.area_name,
                        vessel_count: stats?.[area.area_id]?.vessel_count || 0,
                        total_distance: stats?.[area.area_id]?.total_distance || 0
                    },
                    geometry: JSON.parse(area.geom_json)
                }))
            },
            filled: true,
            stroked: true,
            getFillColor: d => getVesselCountColor(d.properties.vessel_count),
            getLineColor: [200, 100, 0, 255],
            getLineWidth: 3,
            lineWidthMinPixels: 2,
            pickable: true,
            autoHighlight: true,
            highlightColor: [255, 255, 0, 100],
            onClick: (info) => this.handleAreaClick('area', info),
            onRightClick: (info) => this.handleAreaRightClick('area', info)
        });
        
        this.layers.set('area-layer', layer);
        this.updateDeckLayers();
    }

    /**
     * 트랙 레이어 업데이트
     */
    updateTrackLayer(tracks, layerId = 'track-layer') {
        if (!tracks || tracks.length === 0) {
            this.layers.delete(layerId);
            this.updateDeckLayers();
            return;
        }

        const layer = new deck.PathLayer({
            id: layerId,
            data: tracks,
            getPath: d => d.path,
            getColor: d => getTrackColor(d.avg_speed, d.selected),
            getWidth: d => d.selected ? 4 : 3,
            pickable: true,
            widthMinPixels: 2,
            widthMaxPixels: 10,
            capRounded: true,
            jointRounded: true,
            billboard: false
        });
        
        this.layers.set(layerId, layer);
        this.updateDeckLayers();
    }

    /**
     * 위치 레이어 업데이트
     */
    updatePositionLayer(positions) {
        if (!positions || positions.length === 0) {
            this.layers.delete('position-layer');
            this.updateDeckLayers();
            return;
        }

        const layer = new deck.ScatterplotLayer({
            id: 'position-layer',
            data: positions,
            getPosition: d => d.position,
            getRadius: 5,
            radiusMinPixels: 4,
            radiusMaxPixels: 10,
            getFillColor: d => [255, 0, 0, 255],
            getLineColor: [255, 255, 255, 255],
            lineWidthMinPixels: 2,
            stroked: true,
            pickable: true
        });
        
        this.layers.set('position-layer', layer);
        this.updateDeckLayers();
    }

    /**
     * 히트맵 레이어 업데이트
     */
    updateHeatmapLayer(points) {
        if (!points || points.length === 0) {
            this.layers.delete('heatmap-layer');
            this.updateDeckLayers();
            return;
        }

        const layer = new deck.HeatmapLayer({
            id: 'heatmap-layer',
            data: points,
            getPosition: d => d.position,
            getWeight: d => d.weight || 1,
            radiusPixels: 30,
            intensity: 1,
            threshold: 0.05,
            colorRange: [
                [255, 255, 178],
                [254, 217, 118],
                [254, 178, 76],
                [253, 141, 60],
                [240, 59, 32],
                [189, 0, 38]
            ]
        });
        
        this.layers.set('heatmap-layer', layer);
        this.updateDeckLayers();
    }

    /**
     * Deck.gl 레이어 업데이트
     */
    updateDeckLayers() {
        const layers = Array.from(this.layers.values());
        this.deckOverlay.setProps({ layers });
    }

    /**
     * 지도 범위 맞추기
     */
    fitBounds(coordinates) {
        if (!coordinates || coordinates.length === 0) return;
        
        const bounds = calculateBounds(coordinates);
        if (!bounds) return;
        
        this.map.fitBounds([
            [bounds.minLng, bounds.minLat],
            [bounds.maxLng, bounds.maxLat]
        ], {
            padding: 50,
            duration: 1000
        });
    }

    /**
     * 특정 위치로 이동
     */
    flyTo(lng, lat, zoom = 10) {
        this.map.flyTo({
            center: [lng, lat],
            zoom: zoom,
            duration: 1500
        });
    }

    /**
     * 레이어 토글
     */
    toggleLayer(layerId, visible) {
        const layer = this.layers.get(layerId);
        if (layer) {
            layer.visible = visible;
            this.updateDeckLayers();
        }
    }

    /**
     * 모든 레이어 초기화
     */
    clearAllLayers() {
        this.layers.clear();
        this.updateDeckLayers();
    }

    /**
     * 특정 레이어 제거
     */
    removeLayer(layerId) {
        this.layers.delete(layerId);
        this.updateDeckLayers();
    }

    /**
     * 툴팁 생성
     */
    getTooltip({object, layer}) {
        if (!object) return null;
        
        let html = null;
        
        if (layer.id === 'haegu-layer') {
            html = `
                <strong>Haegu ${object.properties.haegu_no}</strong><br>
                선박: ${object.properties.vessel_count}척<br>
                총 거리: ${object.properties.total_distance.toFixed(1)} nm
            `;
        } else if (layer.id === 'area-layer') {
            html = `
                <strong>${object.properties.area_name || object.properties.area_id}</strong><br>
                선박: ${object.properties.vessel_count}척<br>
                총 거리: ${object.properties.total_distance.toFixed(1)} nm
            `;
        } else if (layer.id === 'track-layer' || layer.id === 'all-tracks-layer') {
            html = `
                <strong>선박: ${object.vessel_id}</strong><br>
                평균 속도: ${object.avg_speed.toFixed(1)} kts<br>
                거리: ${object.distance.toFixed(1)} nm
            `;
        } else if (layer.id === 'position-layer') {
            html = `
                <strong>선박: ${object.vessel_id}</strong><br>
                속도: ${object.speed.toFixed(1)} kts<br>
                시간: ${new Date(object.time).toLocaleString('ko-KR')}
            `;
        }
        
        return html ? {
            html: html,
            style: {
                backgroundColor: 'rgba(255, 255, 255, 0.95)',
                color: '#000',
                fontSize: '13px',
                padding: '12px',
                borderRadius: '6px',
                boxShadow: '0 2px 8px rgba(0,0,0,0.15)'
            }
        } : null;
    }

    /**
     * 구역 클릭 핸들러
     */
    handleAreaClick(type, info) {
        if (info.object) {
            this.onAreaClick?.(type, info.object.properties);
        }
        return true;
    }

    /**
     * 구역 우클릭 핸들러
     */
    handleAreaRightClick(type, info) {
        if (info.object) {
            this.onAreaRightClick?.(type, info.object.properties, info);
        }
        return true;
    }

    /**
     * 컨텍스트 메뉴 설정
     */
    setupContextMenu() {
        const canvas = this.map.getCanvas();
        
        canvas.addEventListener('contextmenu', (e) => {
            e.preventDefault();
            
            const pickInfo = this.deckOverlay._deck.pickObject({
                x: e.offsetX,
                y: e.offsetY,
                radius: 1,
                layerIds: ['haegu-layer', 'area-layer']
            });
            
            if (pickInfo && pickInfo.object) {
                const layerId = pickInfo.layer.id;
                const type = layerId === 'haegu-layer' ? 'haegu' : 'area';
                
                this.onContextMenu?.(type, pickInfo.object.properties, {
                    clientX: e.clientX,
                    clientY: e.clientY
                });
            }
        });
    }

    /**
     * 이벤트 핸들러 설정
     */
    setEventHandlers(handlers) {
        this.onAreaClick = handlers.onAreaClick;
        this.onAreaRightClick = handlers.onAreaRightClick;
        this.onContextMenu = handlers.onContextMenu;
    }

    /**
     * 현재 뷰포트 정보 가져오기
     */
    getViewport() {
        const bounds = this.map.getBounds();
        const center = this.map.getCenter();
        const zoom = this.map.getZoom();
        
        return {
            bounds: {
                north: bounds.getNorth(),
                south: bounds.getSouth(),
                east: bounds.getEast(),
                west: bounds.getWest()
            },
            center: {
                lng: center.lng,
                lat: center.lat
            },
            zoom
        };
    }

    /**
     * 스크린샷 캡처
     */
    async captureScreenshot() {
        return new Promise((resolve) => {
            this.map.once('render', () => {
                const canvas = this.map.getCanvas();
                canvas.toBlob((blob) => {
                    resolve(blob);
                });
            });
            this.map.triggerRepaint();
        });
    }
}