/**
 * 지도 컨트롤러 컴포넌트
 */

import { MAP_CONFIG, LAYER_CONFIG, COLORS } from '../utils/constants.js';
import { getColorByType } from '../utils/helpers.js';

export class MapController {
    constructor(containerId = 'map') {
        this.containerId = containerId;
        this.map = null;
        this.deckOverlay = null;
        this.parsedGeoJsonCache = new Map();
    }

    /**
     * 지도 초기화
     */
    async init() {
        return new Promise((resolve) => {
            this.map = new maplibregl.Map({
                container: this.containerId,
                style: {
                    version: 8,
                    sources: {
                        'raster-tiles': {
                            type: 'raster',
                            tiles: ['/api/tiles/world/{z}/{x}/{y}.webp'],
                            tileSize: MAP_CONFIG.TILE_SIZE,
                            attribution: 'Local Tile Server'
                        }
                    },
                    layers: [{
                        id: 'simple-tiles',
                        type: 'raster',
                        source: 'raster-tiles',
                        minzoom: MAP_CONFIG.MIN_ZOOM,
                        maxzoom: MAP_CONFIG.MAX_ZOOM
                    }]
                },
                center: MAP_CONFIG.DEFAULT_CENTER,
                zoom: MAP_CONFIG.DEFAULT_ZOOM
            });
            
            this.map.on('load', () => {
                this.deckOverlay = new deck.MapboxOverlay({
                    layers: []
                });
                
                this.map.addControl(this.deckOverlay);
                this.map.addControl(new maplibregl.NavigationControl());
                resolve();
            });
        });
    }

    /**
     * 지도 업데이트
     * @param {Array} tracks - 표시할 트랙 데이터
     * @param {Set} selectedTracks - 선택된 트랙 ID
     * @param {string} activeVesselId - 활성 선박 ID
     */
    updateMap(tracks, selectedTracks = new Set(), activeVesselId = null) {
        if (!this.deckOverlay) return;
        
        const pathData = [];
        const pointData = [];
        
        // 렌더링할 트랙 결정
        let tracksToRender = [];
        
        if (activeVesselId) {
            tracksToRender = tracks.filter(t => t.vesselId === activeVesselId);
        } else if (selectedTracks.size > 0) {
            tracksToRender = tracks.filter(t => selectedTracks.has(String(t.id)));
        } else {
            tracksToRender = tracks;
        }
        
        // 트랙 데이터 처리
        tracksToRender.forEach(track => {
            const geojson = this.parseTrackGeoJson(track);
            if (!geojson) return;
            
            const isSelected = selectedTracks.has(String(track.id));
            const isInActiveGroup = activeVesselId && track.vesselId === activeVesselId;
            const color = getColorByType(track.abnormalType).slice(0, 3);
            
            // 색상 및 너비 결정
            let finalColor = color;
            let width = LAYER_CONFIG.PATH.DEFAULT_WIDTH;
            let opacity = LAYER_CONFIG.PATH.ACTIVE_OPACITY;
            
            if (isInActiveGroup) {
                if (isSelected) {
                    width = LAYER_CONFIG.PATH.SELECTED_WIDTH;
                    opacity = LAYER_CONFIG.PATH.SELECTED_OPACITY;
                    finalColor = COLORS.SELECTED;
                } else {
                    width = LAYER_CONFIG.PATH.ACTIVE_WIDTH;
                    opacity = LAYER_CONFIG.PATH.ACTIVE_OPACITY;
                }
            } else if (selectedTracks.size > 0 && !isSelected) {
                finalColor = COLORS.DEFAULT_TRACK;
                opacity = LAYER_CONFIG.PATH.INACTIVE_OPACITY;
            }
            
            pathData.push({
                path: geojson.coordinates.map(coord => [coord[0], coord[1]]),
                color: finalColor,
                width: width,
                opacity: opacity,
                trackId: String(track.id),
                vesselId: track.vesselId,
                selected: isSelected,
                isInActiveGroup: isInActiveGroup
            });
            
            // 선택된 트랙의 포인트 표시
            if (isSelected) {
                geojson.coordinates.forEach((coord, idx) => {
                    pointData.push({
                        position: [coord[0], coord[1]],
                        vesselId: track.vesselId,
                        trackId: track.id,
                        time: new Date((coord[2] || 0) * 1000),
                        index: idx,
                        totalPoints: geojson.coordinates.length
                    });
                });
            }
        });
        
        // 선택 상태에 따라 정렬
        pathData.sort((a, b) => {
            if (a.selected && !b.selected) return 1;
            if (!a.selected && b.selected) return -1;
            return 0;
        });
        
        this.renderLayers(pathData, pointData);
    }

    /**
     * 레이어 렌더링
     */
    renderLayers(pathData, pointData) {
        const layers = [
            new deck.PathLayer({
                id: 'tracks',
                data: pathData,
                getPath: d => d.path,
                getColor: d => [...d.color, d.opacity],
                getWidth: d => d.width,
                widthMinPixels: LAYER_CONFIG.PATH.WIDTH_MIN,
                widthMaxPixels: LAYER_CONFIG.PATH.WIDTH_MAX,
                pickable: true,
                autoHighlight: true,
                highlightColor: [255, 255, 0, 200],
                onClick: ({object}) => {
                    if (object && object.trackId) {
                        this.onTrackClick?.(object.trackId);
                    }
                }
            }),
            new deck.ScatterplotLayer({
                id: 'points',
                data: pointData,
                getPosition: d => d.position,
                getFillColor: [255, 255, 255],
                getRadius: LAYER_CONFIG.POINT.RADIUS,
                radiusMinPixels: LAYER_CONFIG.POINT.RADIUS_MIN,
                radiusMaxPixels: LAYER_CONFIG.POINT.RADIUS_MAX,
                stroked: true,
                lineWidthMinPixels: LAYER_CONFIG.POINT.STROKE_WIDTH,
                getLineColor: [0, 0, 0],
                pickable: true,
                onHover: ({object, x, y}) => {
                    this.onPointHover?.(object, x, y);
                }
            })
        ];
        
        this.deckOverlay.setProps({ layers });
    }

    /**
     * GeoJSON 파싱
     */
    parseTrackGeoJson(track) {
        let geojson = this.parsedGeoJsonCache.get(track.id);
        if (!geojson && track.trackGeoJson) {
            try {
                geojson = JSON.parse(track.trackGeoJson);
                this.parsedGeoJsonCache.set(track.id, geojson);
            } catch (e) {
                console.error('Failed to parse GeoJSON:', e);
                return null;
            }
        }
        
        if (geojson && geojson.type === 'LineString') {
            return geojson;
        }
        return null;
    }

    /**
     * 지도를 트랙에 맞게 조정
     */
    fitToTracks(tracks) {
        const bounds = new maplibregl.LngLatBounds();
        
        tracks.forEach(track => {
            const geojson = this.parseTrackGeoJson(track);
            if (geojson) {
                geojson.coordinates.forEach(coord => {
                    bounds.extend([coord[0], coord[1]]);
                });
            }
        });
        
        if (!bounds.isEmpty()) {
            this.map.fitBounds(bounds, { padding: 100 });
        }
    }

    /**
     * 캐시 초기화
     */
    clearCache() {
        this.parsedGeoJsonCache.clear();
    }

    /**
     * 이벤트 핸들러 설정
     */
    setEventHandlers(handlers) {
        if (handlers.onTrackClick) {
            this.onTrackClick = handlers.onTrackClick;
        }
        if (handlers.onPointHover) {
            this.onPointHover = handlers.onPointHover;
        }
    }
}