/**
 * Chunked Streaming GIS Application
 */

import { WebSocketAPI } from '../api/websocket-api.js';
import { ChunkedDataManager } from '../components/chunked-data-manager.js';
import { ChunkedAnimationController } from '../components/chunked-animation-controller.js';
import { ChunkedMapRenderer } from '../components/chunked-map-renderer.js';
import {
    getDefaultTimeRange,
    createTimeRange,
    updateViewportDisplay,
    addLog,
    clearLog,
    toggleDisplay,
    updateButtonState,
    updateProgressBar,
    updateSpeedButtons,
    updateTimelineUI,
    updateStatistics,
    getRenderOptions,
    safeAddEventListener,
    validateQueryParams,
    showError,
    showSuccess,
    getMapViewport
} from '../utils/chunked-utils.js';

export class ChunkedStreamingApp {
    constructor() {
        this.map = null;
        this.websocketAPI = new WebSocketAPI();
        this.dataManager = new ChunkedDataManager();
        this.animationController = new ChunkedAnimationController();
        this.mapRenderer = null;
        
        this.updateLayersTimer = null;
        this.queryStartTime = null;
    }

    /**
     * 애플리케이션 초기화
     */
    async initialize() {
        try {
            this.initializeMap();
            this.setupEventHandlers();
            this.setupWebSocketHandlers();
            this.setDefaultTimeRange();
            
            addLog('시스템 준비 완료', 'success');
        } catch (error) {
            console.error('초기화 실패:', error);
            showError('시스템 초기화에 실패했습니다');
        }
    }

    /**
     * 맵 초기화
     */
    initializeMap() {
        this.map = new maplibregl.Map({
            container: 'mapContainer',
            style: {
                version: 8,
                sources: {
                    'raster-tiles': {
                        type: 'raster',
                        tiles: ['/api/tiles/enc/{z}/{x}/{y}.webp'],
                        tileSize: 256,
                        attribution: 'Local Tile Server'
                    }
                },
                layers: [{
                    id: 'simple-tiles',
                    type: 'raster',
                    source: 'raster-tiles',
                    minzoom: 0,
                    maxzoom: 22
                }]
            },
            center: [128, 35.5],
            zoom: 6
        });

        // 맵 렌더러 초기화
        this.mapRenderer = new ChunkedMapRenderer(this.map);
        this.mapRenderer.initialize();
        this.mapRenderer.setDataManager(this.dataManager);

        // 맵 이벤트 핸들러
        this.map.on('moveend', () => updateViewportDisplay(this.map));
        this.map.on('zoomend', () => updateViewportDisplay(this.map));
    }

    /**
     * 이벤트 핸들러 설정
     */
    setupEventHandlers() {
        // 연결 버튼
        safeAddEventListener('connectBtn', 'click', () => this.connect());
        safeAddEventListener('disconnectBtn', 'click', () => this.disconnect());
        
        // 쿼리 제어
        safeAddEventListener('startBtn', 'click', () => this.startQuery());
        safeAddEventListener('cancelBtn', 'click', () => this.cancelQuery());
        
        // 시간 범위 단축키
        [1, 6, 24, 72, 168].forEach(hours => {
            document.addEventListener('click', (e) => {
                if (e.target.textContent === `${hours === 1 ? '1시간' : hours === 6 ? '6시간' : hours === 24 ? '1일' : hours === 72 ? '3일' : '7일'}`) {
                    this.setTimeRange(hours);
                }
            });
        });
        
        // 애니메이션 제어
        safeAddEventListener('playBtn', 'click', () => this.togglePlay());
        
        // 속도 제어
        document.addEventListener('click', (e) => {
            if (e.target.classList.contains('btn-speed')) {
                const speed = parseFloat(e.target.textContent.replace('x', ''));
                this.setSpeed(speed);
            }
        });
        
        // 타임라인 슬라이더
        safeAddEventListener('timeSlider', 'input', (e) => {
            const progress = parseFloat(e.target.value);
            this.animationController.setTimeFromProgress(progress);
        });
        
        // 렌더링 옵션 변경
        ['showTracks', 'showVessels', 'colorBySpeed', 'trackOpacity'].forEach(id => {
            safeAddEventListener(id, 'change', () => this.updateRenderOptions());
        });
        
        // 로그 초기화
        safeAddEventListener('logContainer', 'click', (e) => {
            if (e.target.textContent === 'Clear') {
                clearLog();
            }
        });
        
        // 전체 초기화 (닫기 버튼)
        document.addEventListener('click', (e) => {
            if (e.target.closest('.btn-close')) {
                this.resetAll();
            }
        });
    }

    /**
     * WebSocket 핸들러 설정
     */
    setupWebSocketHandlers() {
        this.websocketAPI.onConnectionStatusChange((connected) => {
            this.updateConnectionStatus(connected);
        });

        this.websocketAPI.setHandlers({
            response: (response) => this.handleResponse(response),
            status: (status) => this.handleStatus(status),
            chunk: (message) => this.handleChunk(message),
            error: (error) => this.handleError(error)
        });

        // 애니메이션 컨트롤러 이벤트
        this.animationController.setEventHandlers({
            onTimeUpdate: (currentTime) => this.onTimeUpdate(currentTime),
            onPlayStateChange: (playing) => this.onPlayStateChange(playing)
        });
    }

    /**
     * 기본 시간 범위 설정
     */
    setDefaultTimeRange() {
        const timeRange = getDefaultTimeRange();
        document.getElementById('startTime').value = timeRange.startTime;
        document.getElementById('endTime').value = timeRange.endTime;
    }

    /**
     * 시간 범위 설정
     */
    setTimeRange(hours) {
        const timeRange = createTimeRange(hours);
        document.getElementById('startTime').value = timeRange.startTime;
        document.getElementById('endTime').value = timeRange.endTime;
    }

    /**
     * WebSocket 연결
     */
    async connect() {
        try {
            await this.websocketAPI.connect();
            addLog('WebSocket 연결 성공', 'success');
        } catch (error) {
            console.error('연결 실패:', error);
            showError('WebSocket 연결에 실패했습니다');
        }
    }

    /**
     * WebSocket 연결 해제
     */
    async disconnect() {
        try {
            await this.websocketAPI.disconnect();
            addLog('WebSocket 연결 해제', 'info');
        } catch (error) {
            console.error('연결 해제 실패:', error);
        }
    }

    /**
     * 쿼리 시작
     */
    async startQuery() {
        // 입력값 검증
        const startTime = document.getElementById('startTime').value + ':00';
        const endTime = document.getElementById('endTime').value + ':00';
        
        const validation = validateQueryParams(startTime, endTime);
        if (!validation.valid) {
            validation.errors.forEach(error => showError(error));
            return;
        }

        try {
            // 초기화
            this.dataManager.reset();
            this.queryStartTime = Date.now();
            
            // 맵 정보 가져오기
            const { viewport, zoom } = getMapViewport(this.map);
            
            // 애니메이션 시간 설정
            const startTimeMs = new Date(startTime).getTime();
            const endTimeMs = new Date(endTime).getTime();
            this.animationController.setTimeRange(startTimeMs, endTimeMs);
            
            // WebSocket 쿼리 시작
            await this.websocketAPI.startQuery({
                startTime,
                endTime,
                viewport,
                zoomLevel: zoom,
                chunkSize: 20000
            });
            
            // UI 업데이트
            toggleDisplay('startBtn', false);
            toggleDisplay('cancelBtn', true);
            updateProgressBar(0);
            
            addLog('쿼리 시작...', 'info');
            addLog(`요청 시간: ${startTime} ~ ${endTime}`, 'info');
            addLog(`현재 줌 레벨: ${zoom}`, 'info');
            addLog(`뷰포트: [${viewport.minLon.toFixed(4)}, ${viewport.minLat.toFixed(4)}] - [${viewport.maxLon.toFixed(4)}, ${viewport.maxLat.toFixed(4)}]`, 'info');
            
        } catch (error) {
            console.error('쿼리 시작 실패:', error);
            showError('쿼리 시작에 실패했습니다');
        }
    }

    /**
     * 쿼리 취소
     */
    cancelQuery() {
        this.websocketAPI.cancelQuery();
        this.stopTimers();
        this.animationController.stop();
        
        updateButtonState('playBtn', true, '<i class="bi bi-play-fill"></i>');
        addLog('쿼리 취소됨', 'info');
    }

    /**
     * 청크 데이터 처리
     */
    handleChunk(message) {
        const result = this.dataManager.processChunk(message);
        const { chunk, stats } = result;
        
        this.updateStatistics();
        
        // 첫 청크 수신 시 UI 활성화 및 애니메이션 자동 시작
        if (this.dataManager.getStatistics().chunksReceived === 1) {
            toggleDisplay('timelinePanel', true);
            toggleDisplay('legend', true);
            this.setSpeed(50); // 50x 속도 설정
            
            // 애니메이션 자동 시작
            this.animationController.animationState.playing = true;
            this.animationController.forceStart();
            this.onPlayStateChange(true);
        }
        
        // 주기적 레이어 업데이트 (1초마다)
        if (!this.updateLayersTimer) {
            this.updateLayersTimer = setInterval(() => {
                this.updateLayers();
            }, 1000);
        }
        
        // 로그 메시지
        const timeProgress = stats.timeProgress || 0;
        const vesselProgress = stats.vesselProgress || 0;
        const dataStats = this.dataManager.getStatistics();
        
        addLog(
            `청크 ${chunk.chunkIndex + 1}/${chunk.totalChunks || '?'}: ${chunk.compactTracks?.length || 0}척, ${dataStats.pointCount.toLocaleString()}포인트 | 시간: ${timeProgress.toFixed(1)}% | 선박: ${vesselProgress.toFixed(1)}%`,
            'chunk'
        );
    }

    /**
     * 응답 처리
     */
    handleResponse(response) {
        if (response.status === 'STARTED') {
            this.websocketAPI.setCurrentQueryId(response.queryId);
        }
    }

    /**
     * 상태 처리
     */
    handleStatus(status) {
        if (status.progressPercentage >= 0) {
            updateProgressBar(status.progressPercentage);
        }
        
        if (status.status === 'COMPLETED') {
            this.handleComplete();
        }
    }

    /**
     * 에러 처리
     */
    handleError(error) {
        showError(error);
    }

    /**
     * 완료 처리
     */
    handleComplete() {
        const duration = ((Date.now() - this.queryStartTime) / 1000).toFixed(1);
        const stats = this.dataManager.getStatistics();
        
        updateStatistics({ processTime: duration });
        showSuccess(`완료! ${stats.vesselCount}척, ${duration}초 소요`);
        
        // UI 초기화
        toggleDisplay('startBtn', true);
        toggleDisplay('cancelBtn', false);
        updateProgressBar(0);
        
        // 타이머 정리
        this.stopTimers();
        
        // 마지막 레이어 업데이트
        this.updateLayers();
        
        // 맵 범위 조정
        this.mapRenderer.fitMapBounds();
    }

    /**
     * 애니메이션 토글
     */
    togglePlay() {
        // 데이터가 없으면 재생하지 않음
        if (!this.dataManager.hasData()) {
            addLog('재생할 데이터가 없습니다. 먼저 스트리밍을 시작하세요.', 'info');
            return;
        }
        
        // 시간 범위가 설정되지 않았으면 설정
        const timeRange = this.animationController.getTimeRange();
        if (timeRange.startTime === 0 || timeRange.endTime === 0) {
            addLog('애니메이션 시간 범위를 설정 중...', 'info');
            // 현재 입력된 시간으로 설정
            const startTime = new Date(document.getElementById('startTime').value + ':00').getTime();
            const endTime = new Date(document.getElementById('endTime').value + ':00').getTime();
            this.animationController.setTimeRange(startTime, endTime);
        }
        
        this.animationController.togglePlay();
    }

    /**
     * 애니메이션 시작
     */
    startAnimation() {
        if (!this.dataManager.hasData()) {
            return;
        }
        this.animationController.start();
    }

    /**
     * 애니메이션 속도 설정
     */
    setSpeed(speed) {
        this.animationController.setSpeed(speed);
        updateSpeedButtons(speed);
    }

    /**
     * 시간 업데이트 콜백
     */
    onTimeUpdate(currentTime) {
        const timelineData = this.animationController.getTimelineData();
        updateTimelineUI(timelineData);
        this.updateLayers();
    }

    /**
     * 재생 상태 변경 콜백
     */
    onPlayStateChange(playing) {
        const icon = playing ? '<i class="bi bi-pause-fill"></i>' : '<i class="bi bi-play-fill"></i>';
        updateButtonState('playBtn', true, icon);
    }

    /**
     * 렌더링 옵션 업데이트
     */
    updateRenderOptions() {
        const options = getRenderOptions();
        this.mapRenderer.setRenderOptions(options);
        this.updateLayers();
        
        // 범례 표시/숨김
        if (options.showTracks || options.showVessels) {
            toggleDisplay('legend', true);
        }
    }

    /**
     * 레이어 업데이트
     */
    updateLayers() {
        const currentTime = this.animationController.getCurrentTime();
        this.mapRenderer.updateLayers(currentTime);
    }

    /**
     * 연결 상태 업데이트
     */
    updateConnectionStatus(connected) {
        updateButtonState('connectBtn', !connected);
        updateButtonState('disconnectBtn', connected);
        updateButtonState('startBtn', connected);
    }

    /**
     * 통계 정보 업데이트
     */
    updateStatistics() {
        const stats = this.dataManager.getStatistics();
        updateStatistics(stats);
    }

    /**
     * 전체 초기화
     */
    resetAll() {
        // 애니메이션 및 타이머 정리
        this.animationController.reset();
        this.stopTimers();
        
        // 데이터 초기화
        this.dataManager.reset();
        
        // 맵 레이어 초기화
        this.mapRenderer.clearLayers();
        
        // UI 초기화
        toggleDisplay('timelinePanel', false);
        toggleDisplay('legend', false);
        toggleDisplay('startBtn', true);
        toggleDisplay('cancelBtn', false);
        updateProgressBar(0);
        updateButtonState('playBtn', true, '<i class="bi bi-play-fill"></i>');
        
        // 통계 초기화
        this.updateStatistics();
        
        showSuccess('시스템 초기화 완료');
    }

    /**
     * 타이머 정리
     */
    stopTimers() {
        if (this.updateLayersTimer) {
            clearInterval(this.updateLayersTimer);
            this.updateLayersTimer = null;
        }
    }
}

// 전역 인스턴스 생성 및 초기화
let app;

window.addEventListener('load', async () => {
    app = new ChunkedStreamingApp();
    await app.initialize();
});

// 전역 함수들 (기존 HTML에서 onclick 이벤트용)
window.connect = () => app?.connect();
window.disconnect = () => app?.disconnect();
window.startQuery = () => app?.startQuery();
window.cancelQuery = () => app?.cancelQuery();
window.togglePlay = () => app?.togglePlay();
window.setSpeed = (speed) => app?.setSpeed(speed);
window.setTimeRange = (hours) => app?.setTimeRange(hours);
window.resetAll = () => app?.resetAll();
window.clearLog = () => clearLog();

// 디버깅용 전역 함수들
window.debugAnimation = () => {
    if (app) {
        console.log('Animation State:', app.animationController.debugState());
        console.log('Data Manager:', {
            hasData: app.dataManager.hasData(),
            statistics: app.dataManager.getStatistics()
        });
    }
};

window.debugApp = () => app;