/**
 * 汽车360°全景展示应用
 * 支持触摸滑动、自动旋转、惯性效果
 */

class Car360Viewer {
    constructor() {
        // 配置
        this.config = {
            totalFrames: 336,          // 总帧数
            framesPerSwipe: 1,         // 每像素滑动切换的帧数
            inertiaFriction: 0.95,     // 惯性摩擦系数
            minVelocity: 0.1,          // 最小速度阈值
            autoRotateSpeed: 80,       // 自动旋转速度（ms/帧）
            autoRotateDelay: 3000,     // 停止操作后自动旋转延迟（ms）
            imagePath: './images/',    // 图片路径
            imagePrefix: 'car_',       // 图片前缀
            imageExt: '.jpg'           // 图片扩展名
        };

        // 状态
        this.state = {
            currentFrame: 0,
            isDragging: false,
            startX: 0,
            lastX: 0,
            velocity: 0,
            images: [],
            loaded: false,
            animationId: null,
            autoRotateTimer: null,
            autoRotateInterval: null
        };

        // DOM元素
        this.elements = {
            canvas: document.getElementById('carCanvas'),
            loadingScreen: document.getElementById('loadingScreen'),
            loadingProgress: document.getElementById('loadingProgress'),
            loadingText: document.getElementById('loadingText')
        };

        this.ctx = this.elements.canvas.getContext('2d');
        
        this.init();
    }

    init() {
        this.setupCanvas();
        this.bindEvents();
        this.loadImages();
    }

    setupCanvas() {
        const rect = this.elements.canvas.getBoundingClientRect();
        const dpr = window.devicePixelRatio || 1;
        
        this.elements.canvas.width = rect.width * dpr;
        this.elements.canvas.height = rect.height * dpr;
        this.ctx.scale(dpr, dpr);
        
        // 监听窗口大小变化
        window.addEventListener('resize', () => {
            const newRect = this.elements.canvas.getBoundingClientRect();
            this.elements.canvas.width = newRect.width * dpr;
            this.elements.canvas.height = newRect.height * dpr;
            this.ctx.scale(dpr, dpr);
            this.renderFrame(this.state.currentFrame);
        });
    }

    bindEvents() {
        const viewer = this.elements.canvas;
        
        // 触摸事件
        viewer.addEventListener('touchstart', this.handleStart.bind(this), { passive: false });
        viewer.addEventListener('touchmove', this.handleMove.bind(this), { passive: false });
        viewer.addEventListener('touchend', this.handleEnd.bind(this), { passive: false });
    }

    handleStart(e) {
        e.preventDefault();
        this.stopInertia();
        this.stopAutoRotate();
        
        const touch = e.touches[0];
        this.state.isDragging = true;
        this.state.startX = touch.clientX;
        this.state.lastX = touch.clientX;
        this.state.velocity = 0;
    }

    handleMove(e) {
        if (!this.state.isDragging) return;
        e.preventDefault();
        
        const touch = e.touches[0];
        const deltaX = touch.clientX - this.state.lastX;
        
        // 计算速度
        this.state.velocity = deltaX;
        
        // 根据滑动距离更新帧
        const frameDelta = Math.round(deltaX / 5);
        if (frameDelta !== 0) {
            this.state.lastX = touch.clientX;
            this.updateFrame(frameDelta);
        }
    }

    handleEnd(e) {
        if (!this.state.isDragging) return;
        this.state.isDragging = false;
        
        // 启动惯性动画
        if (Math.abs(this.state.velocity) > this.config.minVelocity) {
            this.startInertia();
        } else {
            // 没有惯性，延迟启动自动旋转
            this.scheduleAutoRotate();
        }
    }

    startInertia() {
        const animate = () => {
            this.state.velocity *= this.config.inertiaFriction;
            
            if (Math.abs(this.state.velocity) > this.config.minVelocity) {
                const frameDelta = Math.round(this.state.velocity / 5);
                if (frameDelta !== 0) {
                    this.updateFrame(frameDelta);
                }
                this.state.animationId = requestAnimationFrame(animate);
            } else {
                // 惯性结束，启动自动旋转
                this.scheduleAutoRotate();
            }
        };
        
        this.state.animationId = requestAnimationFrame(animate);
    }

    stopInertia() {
        if (this.state.animationId) {
            cancelAnimationFrame(this.state.animationId);
            this.state.animationId = null;
        }
        this.state.velocity = 0;
    }

    updateFrame(delta) {
        let newFrame = this.state.currentFrame + delta;
        
        // 循环处理
        while (newFrame < 0) newFrame += this.config.totalFrames;
        newFrame = newFrame % this.config.totalFrames;
        
        this.state.currentFrame = newFrame;
        this.renderFrame(newFrame);
    }

    async loadImages() {
        // 首先尝试加载文件系统图片
        try {
            const images = [];
            let loadedCount = 0;
            
            this.updateLoadingProgress(0, '正在加载图片资源...');
            
            for (let i = 0; i < this.config.totalFrames; i++) {
                const img = new Image();
                const frameNum = String(i + 1).padStart(3, '0');
                img.src = `${this.config.imagePath}${this.config.imagePrefix}${frameNum}${this.config.imageExt}`;
                
                await new Promise((resolve, reject) => {
                    img.onload = () => {
                        loadedCount++;
                        const progress = Math.round((loadedCount / this.config.totalFrames) * 100);
                        this.updateLoadingProgress(progress, `加载中 ${loadedCount}/${this.config.totalFrames}`);
                        resolve(img);
                    };
                    img.onerror = () => reject(new Error(`Failed to load frame ${i}`));
                });
                
                images.push(img);
            }
            
            this.updateLoadingProgress(100, '加载完成');
            
            this.state.images = images;
            this.state.loaded = true;
            
            setTimeout(() => {
                this.hideLoading();
                this.renderFrame(0);
            }, 500);
            
            console.log('Loaded', images.length, 'frames from files');
            return;
            
        } catch (error) {
            console.log('File load failed:', error.message);
        }

        // 尝试从 IndexedDB 加载
        this.updateLoadingProgress(0, '正在从缓存加载...');
        const indexedDBFrames = await this.loadFromIndexedDB();
        if (indexedDBFrames && indexedDBFrames.length > 0) {
            this.state.images = indexedDBFrames;
            this.state.loaded = true;
            this.config.totalFrames = indexedDBFrames.length;
            this.updateLoadingProgress(100, '加载完成');
            setTimeout(() => {
                this.hideLoading();
                this.renderFrame(0);
            }, 500);
            return;
        }

        // 演示模式
        console.log('Using demo mode');
        this.updateLoadingProgress(100, '进入演示模式');
        setTimeout(() => {
            this.hideLoading();
            this.startDemoMode();
        }, 500);
    }

    updateLoadingProgress(percent, text) {
        if (this.elements.loadingProgress) {
            this.elements.loadingProgress.style.width = `${percent}%`;
        }
        if (this.elements.loadingText) {
            this.elements.loadingText.textContent = text;
        }
    }

    hideLoading() {
        if (this.elements.loadingScreen) {
            this.elements.loadingScreen.classList.add('hidden');
        }
        // 加载完成后启动自动旋转
        this.startAutoRotate();
    }

    scheduleAutoRotate() {
        // 清除之前的定时器
        if (this.state.autoRotateTimer) {
            clearTimeout(this.state.autoRotateTimer);
        }
        // 延迟启动自动旋转
        this.state.autoRotateTimer = setTimeout(() => {
            this.startAutoRotate();
        }, this.config.autoRotateDelay);
    }

    startAutoRotate() {
        // 清除之前的自动旋转
        this.stopAutoRotate();
        
        // 启动新的自动旋转
        this.state.autoRotateInterval = setInterval(() => {
            this.updateFrame(1);
        }, this.config.autoRotateSpeed);
    }

    stopAutoRotate() {
        if (this.state.autoRotateTimer) {
            clearTimeout(this.state.autoRotateTimer);
            this.state.autoRotateTimer = null;
        }
        if (this.state.autoRotateInterval) {
            clearInterval(this.state.autoRotateInterval);
            this.state.autoRotateInterval = null;
        }
    }

    loadFromIndexedDB() {
        return new Promise((resolve) => {
            const request = indexedDB.open('Car360DB', 1);
            
            request.onerror = () => {
                console.log('IndexedDB error');
                resolve(null);
            };
            
            request.onupgradeneeded = (e) => {
                const db = e.target.result;
                if (!db.objectStoreNames.contains('frames')) {
                    db.createObjectStore('frames', { keyPath: 'id' });
                }
            };
            
            request.onsuccess = async () => {
                const db = request.result;
                
                try {
                    if (!db.objectStoreNames.contains('frames')) {
                        db.close();
                        resolve(null);
                        return;
                    }
                    
                    const tx = db.transaction('frames', 'readonly');
                    const store = tx.objectStore('frames');
                    const getRequest = store.get('frames');
                    
                    getRequest.onsuccess = async () => {
                        if (getRequest.result && getRequest.result.data && getRequest.result.data.length > 0) {
                            console.log('Loading', getRequest.result.data.length, 'frames from IndexedDB');
                            const images = getRequest.result.data.map(dataUrl => {
                                const img = new Image();
                                img.src = dataUrl;
                                return img;
                            });
                            
                            await Promise.all(images.map(img => 
                                new Promise(res => { 
                                    img.onload = () => res(); 
                                    img.onerror = () => res(); 
                                })
                            ));
                            
                            db.close();
                            resolve(images);
                        } else {
                            console.log('No frames data in IndexedDB');
                            db.close();
                            resolve(null);
                        }
                    };
                    
                    getRequest.onerror = () => {
                        console.log('Failed to get frames from IndexedDB');
                        db.close();
                        resolve(null);
                    };
                } catch (e) {
                    console.log('IndexedDB exception:', e);
                    db.close();
                    resolve(null);
                }
            };
        });
    }

    startDemoMode() {
        // 演示模式：生成占位图形
        this.state.loaded = true;
        this.renderFrame(0);
    }

    renderFrame(frameIndex) {
        const canvas = this.elements.canvas;
        const ctx = this.ctx;
        const rect = canvas.getBoundingClientRect();
        const width = rect.width;
        const height = rect.height;
        
        // 清空画布
        ctx.clearRect(0, 0, width, height);
        
        const img = this.state.images[frameIndex];
        if (img && img.complete && img.naturalWidth > 0) {
            // 绘制真实图片
            const scale = Math.max(width / img.naturalWidth, height / img.naturalHeight);
            const x = (width - img.naturalWidth * scale) / 2;
            const y = (height - img.naturalHeight * scale) / 2;
            
            ctx.drawImage(img, x, y, img.naturalWidth * scale, img.naturalHeight * scale);
        } else {
            // 演示模式：绘制占位图形
            this.drawDemoFrame(ctx, width, height, frameIndex);
        }
    }

    drawDemoFrame(ctx, width, height, frameIndex) {
        const angle = (frameIndex / this.config.totalFrames) * Math.PI * 2;
        
        // 背景渐变
        const gradient = ctx.createLinearGradient(0, 0, width, height);
        gradient.addColorStop(0, '#1a1a2e');
        gradient.addColorStop(1, '#16213e');
        ctx.fillStyle = gradient;
        ctx.fillRect(0, 0, width, height);
        
        // 网格效果
        ctx.strokeStyle = 'rgba(0, 212, 255, 0.1)';
        ctx.lineWidth = 1;
        const gridSize = 30;
        
        for (let x = 0; x < width; x += gridSize) {
            ctx.beginPath();
            ctx.moveTo(x, 0);
            ctx.lineTo(x, height);
            ctx.stroke();
        }
        
        for (let y = 0; y < height; y += gridSize) {
            ctx.beginPath();
            ctx.moveTo(0, y);
            ctx.lineTo(width, y);
            ctx.stroke();
        }
        
        // 绘制示意汽车（简化的3D效果）
        const centerX = width / 2;
        const centerY = height / 2;
        
        // 车身主体
        ctx.save();
        ctx.translate(centerX, centerY);
        
        // 阴影
        ctx.fillStyle = 'rgba(0, 0, 0, 0.3)';
        ctx.beginPath();
        ctx.ellipse(0, height * 0.25, width * 0.35, height * 0.08, 0, 0, Math.PI * 2);
        ctx.fill();
        
        // 车身渐变
        const bodyGradient = ctx.createLinearGradient(0, -height * 0.3, 0, height * 0.2);
        bodyGradient.addColorStop(0, '#4a4a5a');
        bodyGradient.addColorStop(0.5, '#2a2a3a');
        bodyGradient.addColorStop(1, '#1a1a2a');
        
        // 车身形状（根据角度变化）
        const perspective = Math.cos(angle);
        const bodyWidth = width * 0.35 * Math.abs(perspective) + width * 0.15;
        const bodyHeight = height * 0.18;
        
        ctx.fillStyle = bodyGradient;
        ctx.beginPath();
        ctx.roundRect(-bodyWidth, -bodyHeight, bodyWidth * 2, bodyHeight * 2, 10);
        ctx.fill();
        
        // 车顶
        const roofGradient = ctx.createLinearGradient(0, -height * 0.35, 0, -height * 0.15);
        roofGradient.addColorStop(0, '#5a5a6a');
        roofGradient.addColorStop(1, '#3a3a4a');
        
        ctx.fillStyle = roofGradient;
        ctx.beginPath();
        ctx.roundRect(-bodyWidth * 0.7, -height * 0.35, bodyWidth * 1.4, height * 0.2, [15, 15, 5, 5]);
        ctx.fill();
        
        // 车窗
        ctx.fillStyle = 'rgba(0, 212, 255, 0.3)';
        ctx.beginPath();
        const windowWidth = bodyWidth * 0.5;
        ctx.roundRect(-windowWidth, -height * 0.32, windowWidth * 2, height * 0.12, 5);
        ctx.fill();
        
        // 车灯光效
        const lightIntensity = 0.5 + Math.sin(angle * 2) * 0.3;
        
        // 左车灯
        const leftLightGradient = ctx.createRadialGradient(
            -bodyWidth * 0.8, 0, 0,
            -bodyWidth * 0.8, 0, 30
        );
        leftLightGradient.addColorStop(0, `rgba(255, 220, 100, ${lightIntensity})`);
        leftLightGradient.addColorStop(1, 'rgba(255, 220, 100, 0)');
        ctx.fillStyle = leftLightGradient;
        ctx.beginPath();
        ctx.arc(-bodyWidth * 0.8, 0, 30, 0, Math.PI * 2);
        ctx.fill();
        
        // 右车灯
        const rightLightGradient = ctx.createRadialGradient(
            bodyWidth * 0.8, 0, 0,
            bodyWidth * 0.8, 0, 30
        );
        rightLightGradient.addColorStop(0, `rgba(255, 100, 100, ${lightIntensity})`);
        rightLightGradient.addColorStop(1, 'rgba(255, 100, 100, 0)');
        ctx.fillStyle = rightLightGradient;
        ctx.beginPath();
        ctx.arc(bodyWidth * 0.8, 0, 30, 0, Math.PI * 2);
        ctx.fill();
        
        // 车轮
        ctx.fillStyle = '#1a1a2a';
        ctx.strokeStyle = '#3a3a4a';
        ctx.lineWidth = 3;
        
        // 左轮
        ctx.beginPath();
        ctx.ellipse(-bodyWidth * 0.6, bodyHeight, 25, 20, 0, 0, Math.PI * 2);
        ctx.fill();
        ctx.stroke();
        
        // 右轮
        ctx.beginPath();
        ctx.ellipse(bodyWidth * 0.6, bodyHeight, 25, 20, 0, 0, Math.PI * 2);
        ctx.fill();
        ctx.stroke();
        
        ctx.restore();
        
        // 帧号显示
        ctx.fillStyle = 'rgba(255, 255, 255, 0.5)';
        ctx.font = '14px monospace';
        ctx.textAlign = 'center';
        ctx.fillText(`帧 ${frameIndex + 1}/${this.config.totalFrames}`, centerX, height - 20);
        
        // 演示模式提示
        ctx.fillStyle = 'rgba(0, 212, 255, 0.6)';
        ctx.font = '12px sans-serif';
        ctx.fillText('演示模式 - 请添加实际序列帧图片到 images 文件夹', centerX, 30);
    }
}

// 初始化应用
document.addEventListener('DOMContentLoaded', () => {
    window.carViewer = new Car360Viewer();
});
