/**
 * 模拟 ARKit 数据的 WebSocket 服务器
 * 运行: node mock-arkit-server.js
 */

const WebSocket = require('ws');

const PORT = 8765;
const wss = new WebSocket.Server({ port: PORT });

// ARKit 52 个 blendShape 完整列表
const ARKIT_BLENDSHAPES = [
    'eyeBlinkLeft', 'eyeLookDownLeft', 'eyeLookInLeft', 'eyeLookOutLeft', 'eyeLookUpLeft', 'eyeSquintLeft', 'eyeWideLeft',
    'eyeBlinkRight', 'eyeLookDownRight', 'eyeLookInRight', 'eyeLookOutRight', 'eyeLookUpRight', 'eyeSquintRight', 'eyeWideRight',
    'jawForward', 'jawLeft', 'jawRight', 'jawOpen',
    'mouthClose', 'mouthFunnel', 'mouthPucker', 'mouthLeft', 'mouthRight',
    'mouthSmileLeft', 'mouthSmileRight', 'mouthFrownLeft', 'mouthFrownRight',
    'mouthDimpleLeft', 'mouthDimpleRight', 'mouthStretchLeft', 'mouthStretchRight',
    'mouthRollLower', 'mouthRollUpper', 'mouthShrugLower', 'mouthShrugUpper',
    'mouthPressLeft', 'mouthPressRight', 'mouthLowerDownLeft', 'mouthLowerDownRight',
    'mouthUpperUpLeft', 'mouthUpperUpRight',
    'browDownLeft', 'browDownRight', 'browInnerUp', 'browOuterUpLeft', 'browOuterUpRight',
    'cheekPuff', 'cheekSquintLeft', 'cheekSquintRight',
    'noseSneerLeft', 'noseSneerRight', 'tongueOut'
];

// 表情预设
const expressions = [
    { name: '微笑', data: { mouthSmileLeft: 0.8, mouthSmileRight: 0.8, cheekSquintLeft: 0.3, cheekSquintRight: 0.3 } },
    { name: '张嘴说话', data: { jawOpen: 0.5, mouthFunnel: 0.3 } },
    { name: '惊讶', data: { eyeWideLeft: 0.9, eyeWideRight: 0.9, jawOpen: 0.6, browInnerUp: 0.7 } },
    { name: '皱眉', data: { browDownLeft: 0.8, browDownRight: 0.8, eyeSquintLeft: 0.3, eyeSquintRight: 0.3 } },
    { name: '嘟嘴', data: { mouthPucker: 0.9, mouthFunnel: 0.4 } },
    { name: '吐舌', data: { tongueOut: 0.7, jawOpen: 0.4 } },
    { name: '生气', data: { noseSneerLeft: 0.7, noseSneerRight: 0.7, browDownLeft: 0.6, browDownRight: 0.6, jawOpen: 0.2 } },
    { name: '悲伤', data: { mouthFrownLeft: 0.7, mouthFrownRight: 0.7, browInnerUp: 0.5, eyeSquintLeft: 0.2, eyeSquintRight: 0.2 } },
    { name: '中性', data: {} },
];

let currentExprIndex = 0;
let transitionProgress = 0;
let blinkTimer = 0;
let isBlinking = false;

function lerp(a, b, t) {
    return a + (b - a) * t;
}

function generateBlendShapes() {
    const current = expressions[currentExprIndex].data;
    const next = expressions[(currentExprIndex + 1) % expressions.length].data;

    // 初始化所有 52 个 blendShape 为 0
    const blendShapes = {};
    ARKIT_BLENDSHAPES.forEach(name => blendShapes[name] = 0);

    // 插值当前和下一个表情
    for (const key of ARKIT_BLENDSHAPES) {
        const currentVal = current[key] || 0;
        const nextVal = next[key] || 0;
        blendShapes[key] = lerp(currentVal, nextVal, transitionProgress);
    }

    // 自然眨眼（每3-5秒眨一次）
    blinkTimer++;
    if (!isBlinking && blinkTimer > 90 + Math.random() * 60) {
        isBlinking = true;
        blinkTimer = 0;
    }
    if (isBlinking) {
        const blinkProgress = blinkTimer / 6;
        if (blinkProgress < 1) {
            blendShapes.eyeBlinkLeft = Math.sin(blinkProgress * Math.PI);
            blendShapes.eyeBlinkRight = Math.sin(blinkProgress * Math.PI);
        } else {
            isBlinking = false;
            blinkTimer = 0;
        }
    }

    // 添加微小的随机抖动（更自然）
    blendShapes.jawOpen += (Math.random() - 0.5) * 0.02;
    blendShapes.browInnerUp += (Math.random() - 0.5) * 0.01;

    // 表情过渡
    transitionProgress += 0.015;
    if (transitionProgress >= 1) {
        transitionProgress = 0;
        currentExprIndex = (currentExprIndex + 1) % expressions.length;
        console.log(`切换到表情: ${expressions[currentExprIndex].name}`);
    }

    return blendShapes;
}

wss.on('connection', (ws) => {
    console.log('客户端已连接');

    const interval = setInterval(() => {
        if (ws.readyState === WebSocket.OPEN) {
            const data = generateBlendShapes();
            ws.send(JSON.stringify(data));
        }
    }, 33); // ~30fps

    ws.on('close', () => {
        console.log('客户端断开');
        clearInterval(interval);
    });
});

console.log(`ARKit 模拟服务器运行在 ws://localhost:${PORT}`);
console.log('表情循环: ' + expressions.map(e => e.name).join(' -> '));
