#include "utils_synchronizer_v2.h"
#include "qdebug.h"
#include "qglobal.h"
#include <algorithm>
#include <cmath>
#include <iostream>
#include <sstream>

namespace av {
namespace utils {

// 构造函数
SynchronizerV2::SynchronizerV2(const SyncConfigV2& config)
    : m_config(config)
    , m_syncStrategy(config.strategy)
    , m_playbackSpeed(1.0)
{
    // 初始化时钟
    initClock(m_audioClock, 0);
    initClock(m_videoClock, 0);
    initClock(m_externalClock, 0);
    
    // 初始化帧计时器
    m_frameTimer = getCurrentTime();
}

// 析构函数
SynchronizerV2::~SynchronizerV2() {
    close();
}

// 初始化
ErrorCode SynchronizerV2::initialize() {
    if (m_initialized) {
        return ErrorCode::SUCCESS;
    }
    
    // 重置状态
    m_initialized = true;
    m_running = false;
    m_paused = false;
    
    // 重置时钟
    initClock(m_audioClock, 0);
    initClock(m_videoClock, 0);
    initClock(m_externalClock, 0);
    
    // 重置帧计时器
    m_frameTimer = getCurrentTime();
    
    // 重置统计信息
    std::lock_guard<std::mutex> lock(m_statsMutex);
    m_stats = SyncStatsV2();
    
    return ErrorCode::SUCCESS;
}

// 关闭
void SynchronizerV2::close() {
    if (!m_initialized) {
        return;
    }
    
    stop();
    m_initialized = false;
}

// 启动
ErrorCode SynchronizerV2::start() {
    if (!m_initialized) {
        return ErrorCode::NOT_INITIALIZED;
    }
    
    if (m_running) {
        return ErrorCode::SUCCESS;
    }
    
    // 重置帧计时器
    m_frameTimer = getCurrentTime();
    
    // 更新外部时钟
    updateExternalClock();
    
    m_running = true;
    m_paused = false;
    
    return ErrorCode::SUCCESS;
}

// 停止
ErrorCode SynchronizerV2::stop() {
    if (!m_initialized || !m_running) {
        return ErrorCode::SUCCESS;
    }
    
    m_running = false;
    m_paused = false;
    
    return ErrorCode::SUCCESS;
}

// 暂停
ErrorCode SynchronizerV2::pause() {
    if (!m_initialized || !m_running) {
        return ErrorCode::NOT_STARTED;
    }
    
    if (m_paused) {
        return ErrorCode::SUCCESS;
    }
    {
        // 设置时钟暂停状态
        std::lock_guard<std::mutex> lock(m_clockMutex);
        m_audioClock.paused = true;
        m_videoClock.paused = true;
        m_externalClock.paused = true;
    }
    m_paused = true;
    
    return ErrorCode::SUCCESS;
}

// 恢复
ErrorCode SynchronizerV2::resume() {
    if (!m_initialized || !m_running) {
        return ErrorCode::NOT_STARTED;
    }
    
    if (!m_paused) {
        return ErrorCode::SUCCESS;
    }
    // 防止互斥死锁
    {
        // 恢复时钟暂停状态
        std::lock_guard<std::mutex> lock(m_clockMutex);
        m_audioClock.paused = false;
        m_videoClock.paused = false;
        m_externalClock.paused = false;
    }
    // 更新外部时钟
    updateExternalClock();
    
    m_paused = false;
    
    return ErrorCode::SUCCESS;
}

// 重置
ErrorCode SynchronizerV2::reset() {
    if (!m_initialized) {
        return ErrorCode::NOT_INITIALIZED;
    }
    
    // 重置时钟
    std::lock_guard<std::mutex> lock(m_clockMutex);
    initClock(m_audioClock, m_audioSerial);
    initClock(m_videoClock, m_videoSerial);
    initClock(m_externalClock, m_externalSerial);
    
    // 重置帧计时器
    m_frameTimer = getCurrentTime();
    
    // 重置音频同步状态
    m_audioDiffCum = 0.0;
    m_audioDiffAvgCount = 0;
    
    // 重置统计信息
    {
        std::lock_guard<std::mutex> statsLock(m_statsMutex);
        m_stats = SyncStatsV2();
        m_stats.playbackSpeed = m_playbackSpeed;
    }
    return ErrorCode::SUCCESS;
}

// 设置流信息
void SynchronizerV2::setStreamInfo(bool hasAudio, bool hasVideo) {
    m_hasAudio = hasAudio;
    m_hasVideo = hasVideo;

    // // 如果没有音频，但同步策略是音频主时钟，则切换到视频主时钟
    // if (!hasAudio && m_syncStrategy == SyncStrategy::AUDIO_MASTER) {
    //     if (hasVideo) {
    //         setSyncStrategy(SyncStrategy::VIDEO_MASTER);
    //     } else {
    //         setSyncStrategy(SyncStrategy::EXTERNAL_MASTER);
    //     }
    // }

    // // 如果没有视频，但同步策略是视频主时钟，则切换到音频主时钟
    // if (!hasVideo && m_syncStrategy == SyncStrategy::VIDEO_MASTER) {
    //     if (hasAudio) {
    //         setSyncStrategy(SyncStrategy::AUDIO_MASTER);
    //     } else {
    //         setSyncStrategy(SyncStrategy::EXTERNAL_MASTER);
    //     }
    // }

    // 根据可用流调整同步策略
    if (hasAudio && hasVideo) {
        // 两种流都有，使用音频优先
        setSyncStrategy(SyncStrategy::AUDIO_MASTER);
    } else if (hasVideo && !hasAudio) {
        // 只有视频，强制使用视频主时钟
        setSyncStrategy(SyncStrategy::VIDEO_MASTER);
    } else if (hasAudio && !hasVideo) {
        // 只有音频，强制使用音频主时钟
        setSyncStrategy(SyncStrategy::AUDIO_MASTER);
    } else {
        // 两种流都没有，使用外部时钟
        setSyncStrategy(SyncStrategy::EXTERNAL_MASTER);
    }
}

// 获取时钟值
double SynchronizerV2::getClock(ClockType type) const {
    std::lock_guard<std::mutex> lock(m_clockMutex);
    
    const Clock* clock = nullptr;
    switch (type) {
        case ClockType::AUDIO:
            clock = &m_audioClock;
            break;
        case ClockType::VIDEO:
            clock = &m_videoClock;
            break;
        case ClockType::EXTERNAL:
            clock = &m_externalClock;
            break;
    }
    
    if (!clock) {
        return 0.0;
    }
    
    // 如果时钟暂停，直接返回pts
    if (clock->paused) {
        return clock->pts;
    }
    
    double time = getCurrentTime();
    // 计算当前时钟时间 = pts + (当前时间 - 上次更新时间) * 速度
    // return clock->ptsDrift + (time - clock->lastUpdated) * clock->speed;

    return clock->ptsDrift + time + (time - clock->lastUpdated) * (1.0 - clock->speed);
}

// 设置时钟
void SynchronizerV2::setClock(ClockType type, double pts, int serial) {
    setClockAt(type, pts, serial, getCurrentTime());
}

// 在指定时间设置时钟
void SynchronizerV2::setClockAt(ClockType type, double pts, int serial, double time) {
    std::lock_guard<std::mutex> lock(m_clockMutex);
    if (m_paused) {
        qDebug() << "setClockAt-->:" << (int) type << pts << serial << time;
    }
    Clock* clock = nullptr;
    switch (type) {
        case ClockType::AUDIO:
            clock = &m_audioClock;
            break;
        case ClockType::VIDEO:
            clock = &m_videoClock;
            break;
        case ClockType::EXTERNAL:
            clock = &m_externalClock;
            break;
    }
    
    if (!clock) {
        return;
    }
    
    // 更新时钟
    clock->pts = pts;
    clock->lastUpdated = time;
    clock->ptsDrift = clock->pts - time;
    clock->serial = serial;
    
    // 更新统计信息
    //updateStats();
}

// 设置时钟速度
void SynchronizerV2::setClockSpeed(ClockType type, double speed) {
    //std::lock_guard<std::mutex> lock(m_clockMutex);

    Clock* clock = nullptr;
    switch (type) {
        case ClockType::AUDIO:
            clock = &m_audioClock;
            break;
        case ClockType::VIDEO:
            clock = &m_videoClock;
            break;
        case ClockType::EXTERNAL:
            clock = &m_externalClock;
            break;
    }
    
    if (!clock) {
        return;
    }
    
    // 设置时钟速度前先更新当前pts
    double pts = getClock(type);
    clock->pts = pts;
    clock->lastUpdated = getCurrentTime();
    clock->ptsDrift = clock->pts - clock->lastUpdated;
    clock->speed = speed;
}

// 获取主时钟类型
ClockType SynchronizerV2::getMasterClockType() const {
    // 根据同步策略和流信息确定主时钟类型
    switch (m_syncStrategy) {
        case SyncStrategy::AUDIO_MASTER:
            if (m_hasAudio) {
                return ClockType::AUDIO;
            }
            break;
        case SyncStrategy::VIDEO_MASTER:
            if (m_hasVideo) {
                return ClockType::VIDEO;
            }
            break;
        case SyncStrategy::EXTERNAL_MASTER:
            return ClockType::EXTERNAL;
    }
    
    // 如果首选的主时钟不可用，则按优先级选择
    if (m_hasAudio) {
        return ClockType::AUDIO;
    } else if (m_hasVideo) {
        return ClockType::VIDEO;
    } else {
        return ClockType::EXTERNAL;
    }
}

// 获取主时钟值
double SynchronizerV2::getMasterClock() const {
    ClockType masterType = getMasterClockType();
    return getClock(masterType);
}

// 计算视频帧目标延迟
double SynchronizerV2::computeTargetDelay(double frameDuration, double videoPts) const {
    double delay = 0.0;
    
    // 如果不是视频主时钟，则需要与主时钟同步
    if (getMasterClockType() != ClockType::VIDEO) {
        // 计算视频时钟与主时钟的差异
        double diff = videoPts - getMasterClock();
        
        // 如果差异太大（超过noSyncThreshold），则不进行同步
        if (std::fabs(diff) < m_config.noSyncThreshold) {
            // 如果视频落后于主时钟或超前太多，则调整延迟
            if (diff <= -m_config.syncThresholdMin) {  // 视频落后，减少延迟
                delay = std::max(0.0, delay + diff);
            } else if (diff >= m_config.syncThresholdMax) {  // 视频超前太多，增加延迟
                delay = delay + diff;
            } else if (diff >= m_config.syncThresholdMin) {  // 视频略微超前，平滑调整
                delay = (delay + diff) * 2.0 / 3.0;
            }
        }
    }
    
    // 添加帧持续时间
    delay += frameDuration;
    
    return delay;
}

// 同步视频帧
FrameDecision SynchronizerV2::synchronizeVideo(double pts, int serial, double duration) const {
    FrameDecision decision;
    
    // 如果没有视频流，直接显示
    if (!m_hasVideo) {
        decision.action = FrameAction::DISPLAY;
        decision.delay = 0.0;
        decision.reason = "No video stream";
        return decision;
    }
    
    // 如果暂停，直接显示
    if (m_paused) {
        decision.action = FrameAction::DISPLAY;
        decision.delay = 0.0;
        decision.reason = "Playback paused";
        return decision;
    }
    
    // 计算目标延迟
    double delay = computeTargetDelay(duration, pts);
    
    // 获取当前时间
    double time = getCurrentTime();
    
    // 计算实际延迟（相对于上一帧的显示时间）
    double actualDelay = time - m_frameTimer;
    
    // 计算同步误差
    double syncError = 0.0;
    if (getMasterClockType() != ClockType::VIDEO) {
        syncError = pts - getMasterClock();
    }
    
    // 更新帧计时器
    m_frameTimer += delay;
    
    // 如果实际延迟大于两倍目标延迟，说明系统可能卡顿，重置帧计时器
    if (actualDelay > 2.0 * delay) {
        m_frameTimer = time;
    }
    
    // 决定帧处理动作
    if (time < m_frameTimer) {
        // 当前时间小于下一帧显示时间，需要等待
        decision.action = FrameAction::DISPLAY;
        decision.delay = m_frameTimer - time;  // 需要等待的时间
        decision.syncError = syncError;
        decision.reason = "Wait for next frame time";
    } else {
        // 当前时间已经超过下一帧显示时间
        
        // 如果延迟太大，可能需要丢帧
        if (time > m_frameTimer + m_config.frameDropThreshold && getMasterClockType() != ClockType::VIDEO) {
            decision.action = FrameAction::DROP;
            decision.delay = 0.0;
            decision.syncError = syncError;
            decision.reason = "Frame too late, dropping";
            
            // 通知帧丢弃
            notifyFrameDrop(ClockType::VIDEO, static_cast<int64_t>(pts * 1000));
        } else {
            // 正常显示
            decision.action = FrameAction::DISPLAY;
            decision.delay = 0.0;  // 立即显示
            decision.syncError = syncError;
            decision.reason = "Display immediately";
        }
    }
    
    // 通知同步误差
    if (std::fabs(syncError) > m_config.syncThresholdMin) {
        notifySyncError(syncError, decision.reason);
    }
    
    return decision;
}

// 同步音频
int SynchronizerV2::synchronizeAudio(short* samples, int samplesSize, double pts) {
    // 如果没有音频流或者音频是主时钟，则不需要同步
    if (!m_hasAudio || getMasterClockType() == ClockType::AUDIO || m_paused) {
        return samplesSize;
    }
    
    // 计算音频与主时钟的差异
    double diff = getClock(ClockType::AUDIO) - getMasterClock();
    
    // 如果差异太大，则不进行同步
    if (std::fabs(diff) > m_config.noSyncThreshold) {
        // 重置音频差异累积
        m_audioDiffCum = 0.0;
        m_audioDiffAvgCount = 0;
        return samplesSize;
    }
    
    // 更新音频差异平均值
    m_audioDiffCum = diff + m_audioDiffCum * (1.0 - m_config.audioDiffAvgCoef);
    if (m_audioDiffAvgCount < m_config.audioDiffAvgCount) {
        m_audioDiffAvgCount++;
    } else {
        double avgDiff = m_audioDiffCum / m_audioDiffAvgCount;
        
        // 根据差异调整音频样本数量
        if (std::fabs(avgDiff) >= m_config.audioDiffThreshold) {
            int wantedSamples = samplesSize;
            int minSamples = samplesSize * (1.0 - m_config.audioDiffThreshold);
            int maxSamples = samplesSize * (1.0 + m_config.audioDiffThreshold);
            
            // 计算调整后的样本数量
            wantedSamples += static_cast<int>(diff * samplesSize);
            wantedSamples = std::max(minSamples, std::min(wantedSamples, maxSamples));
            
            return wantedSamples;
        }
    }
    
    return samplesSize;
}

// 设置配置
void SynchronizerV2::setConfig(const SyncConfigV2& config) {
    m_config = config;
    m_syncStrategy = config.strategy;
}

// 获取配置
SyncConfigV2 SynchronizerV2::getConfig() const {
    return m_config;
}

// 设置同步策略
void SynchronizerV2::setSyncStrategy(SyncStrategy strategy) {
    // 检查策略是否可用
    if (strategy == SyncStrategy::AUDIO_MASTER && !m_hasAudio) {
        if (m_hasVideo) {
            strategy = SyncStrategy::VIDEO_MASTER;
        } else {
            strategy = SyncStrategy::EXTERNAL_MASTER;
        }
    } else if (strategy == SyncStrategy::VIDEO_MASTER && !m_hasVideo) {
        if (m_hasAudio) {
            strategy = SyncStrategy::AUDIO_MASTER;
        } else {
            strategy = SyncStrategy::EXTERNAL_MASTER;
        }
    }
    
    m_syncStrategy = strategy;
    m_config.strategy = strategy;
}

// 获取同步策略
SyncStrategy SynchronizerV2::getSyncStrategy() const {
    return m_syncStrategy;
}

// 设置播放速度
void SynchronizerV2::setPlaybackSpeed(double speed) {
    // 限制速度范围
    speed = std::max(m_config.clockSpeedMin, std::min(speed, m_config.clockSpeedMax));
    
    // 如果速度没有变化，则不需要更新
    if (std::fabs(speed - m_playbackSpeed) < 0.01) {
        return;
    }
    
    // 更新播放速度
    m_playbackSpeed = speed;
    
    // 更新所有时钟的速度
    setClockSpeed(ClockType::AUDIO, speed);
    setClockSpeed(ClockType::VIDEO, speed);
    setClockSpeed(ClockType::EXTERNAL, speed);
    
    // 更新统计信息
    std::lock_guard<std::mutex> lock(m_statsMutex);
    m_stats.playbackSpeed = speed;
}

// 获取播放速度
double SynchronizerV2::getPlaybackSpeed() const {
    return m_playbackSpeed;
}

// 获取统计信息
SyncStatsV2 SynchronizerV2::getStats() const {
    std::lock_guard<std::mutex> lock(m_statsMutex);
    return m_stats;
}

// 设置同步错误回调
void SynchronizerV2::setSyncErrorCallback(const SyncErrorCallback& callback) {
    std::lock_guard<std::mutex> lock(m_callbackMutex);
    m_syncErrorCallback = callback;
}

// 设置帧丢弃回调
void SynchronizerV2::setFrameDropCallback(const FrameDropCallback& callback) {
    std::lock_guard<std::mutex> lock(m_callbackMutex);
    m_frameDropCallback = callback;
}

// 获取调试信息
std::string SynchronizerV2::getDebugInfo() const {
    std::stringstream ss;
    ss.precision(4);
    // 获取当前状态
    bool initialized = m_initialized;
    bool running = m_running;
    bool paused = m_paused;
    
    // 获取时钟值
    double audioClock = getClock(ClockType::AUDIO);
    double videoClock = getClock(ClockType::VIDEO);
    double externalClock = getClock(ClockType::EXTERNAL);
    double masterClock = getMasterClock();
    
    // 获取同步策略
    SyncStrategy strategy = getSyncStrategy();
    std::string strategyStr;
    switch (strategy) {
        case SyncStrategy::AUDIO_MASTER:
            strategyStr = "AUDIO_MASTER";
            break;
        case SyncStrategy::VIDEO_MASTER:
            strategyStr = "VIDEO_MASTER";
            break;
        case SyncStrategy::EXTERNAL_MASTER:
            strategyStr = "EXTERNAL_MASTER";
            break;
    }
    
    // 获取主时钟类型
    ClockType masterType = getMasterClockType();
    std::string masterTypeStr;
    switch (masterType) {
        case ClockType::AUDIO:
            masterTypeStr = "AUDIO";
            break;
        case ClockType::VIDEO:
            masterTypeStr = "VIDEO";
            break;
        case ClockType::EXTERNAL:
            masterTypeStr = "EXTERNAL";
            break;
    }
    
    // 获取统计信息
    SyncStatsV2 stats = getStats();
    
    // 构建调试信息
    ss << "SynchronizerV2 Debug Info:\n";
    ss << "  State: " << (initialized ? "Initialized" : "Not Initialized")
       << ", " << (running ? "Running" : "Stopped")
       << ", " << (paused ? "Paused" : "Playing") << "\n";
    ss << "  Streams: " << (m_hasAudio ? "Audio" : "No Audio")
       << ", " << (m_hasVideo ? "Video" : "No Video") << "\n";
    ss << "  Sync Strategy: " << strategyStr << "\n";
    ss << "  CurrentTime: " << getCurrentTime() << "\n";
    ss << "  Master Clock Type: " << masterTypeStr << "\n";
    ss << "  Clocks (seconds):\n";
    ss << "    Audio: " << audioClock << "\n";
    ss << "    Video: " << videoClock << "\n";
    ss << "    External: " << externalClock << "\n";
    ss << "    Master: " << masterClock << "\n";
    ss << "  Playback Speed: " << m_playbackSpeed << "\n";
    ss << "  Stats:\n";
    ss << "    Audio-Video Sync Error: " << stats.audioVideoSyncError << " seconds\n";
    ss << "    Avg Sync Error: " << stats.avgSyncError << " seconds\n";
    ss << "    Max Sync Error: " << stats.maxSyncError << " seconds\n";
    ss << "    Dropped Frames: " << stats.droppedFrames << "\n";
    ss << "    Duplicated Frames: " << stats.duplicatedFrames << "\n";
    
    return ss.str();
}

// 初始化时钟
void SynchronizerV2::initClock(Clock& clock, int serial) {
    clock.pts = 0.0;
    clock.ptsDrift = 0.0;
    clock.lastUpdated = getCurrentTime();
    clock.speed = m_playbackSpeed;
    clock.serial = serial;
    clock.paused = false;
    clock.queueSerial = serial;
}

// 将时钟同步到从属时钟
void SynchronizerV2::syncClockToSlave(Clock& c, const Clock& slave) {
    double clockDiff = getClock(ClockType::EXTERNAL) - getClock(ClockType::AUDIO);
    double correction = 0.0;
    
    // 根据差异调整时钟速度
    if (std::fabs(clockDiff) < m_config.noSyncThreshold) {
        if (clockDiff <= -m_config.syncThresholdMin) {
            // 外部时钟落后，加速
            correction = -m_config.clockSpeedStep;
        } else if (clockDiff >= m_config.syncThresholdMin) {
            // 外部时钟超前，减速
            correction = m_config.clockSpeedStep;
        }
        
        // 应用速度调整
        c.speed = m_playbackSpeed + correction;
        c.speed = std::max(m_config.clockSpeedMin, std::min(c.speed, m_config.clockSpeedMax));
    }
}

// 更新外部时钟
void SynchronizerV2::updateExternalClock() {
    // 更新外部时钟，使其与主时钟同步
    if (getMasterClockType() != ClockType::EXTERNAL) {
        double masterClock = getMasterClock();
        setClock(ClockType::EXTERNAL, masterClock, m_externalSerial);
    }
}

// 检查外部时钟速度
void SynchronizerV2::checkExternalClockSpeed() {
    if (m_hasAudio && getMasterClockType() == ClockType::EXTERNAL) {
        // 将外部时钟同步到音频时钟
        syncClockToSlave(m_externalClock, m_audioClock);
    } else if (m_hasVideo && getMasterClockType() == ClockType::EXTERNAL) {
        // 将外部时钟同步到视频时钟
        syncClockToSlave(m_externalClock, m_videoClock);
    }
}

// 获取当前时间（秒）
double SynchronizerV2::getCurrentTime() const
{
    return av_gettime_relative() / 1000000.0;
}

// 更新统计信息
void SynchronizerV2::updateStats() {
    std::lock_guard<std::mutex> lock(m_statsMutex);
    
    // 更新时钟值
    m_stats.audioClock = getClock(ClockType::AUDIO);
    m_stats.videoClock = getClock(ClockType::VIDEO);
    m_stats.externalClock = getClock(ClockType::EXTERNAL);
    m_stats.masterClock = getMasterClock();
    
    // 计算音视频同步误差
    if (m_hasAudio && m_hasVideo) {
        m_stats.audioVideoSyncError = m_stats.audioClock - m_stats.videoClock;
        
        // 更新平均同步误差
        double absError = std::fabs(m_stats.audioVideoSyncError);
        m_stats.avgSyncError = (m_stats.avgSyncError * 0.9) + (absError * 0.1);
        
        // 更新最大同步误差
        if (absError > m_stats.maxSyncError) {
            m_stats.maxSyncError = absError;
        }
    }
    
    // 更新播放速度
    m_stats.playbackSpeed = m_playbackSpeed;
}

// 通知同步错误
void SynchronizerV2::notifySyncError(double error, const std::string& reason) const {
    std::lock_guard<std::mutex> lock(m_callbackMutex);
    if (m_syncErrorCallback) {
        m_syncErrorCallback(error, reason);
    }
}

// 通知帧丢弃
void SynchronizerV2::notifyFrameDrop(ClockType type, int64_t pts) const {
    std::lock_guard<std::mutex> lock(m_callbackMutex);
    if (m_frameDropCallback) {
        m_frameDropCallback(type, pts);
    }
    
    // 更新统计信息
    std::lock_guard<std::mutex> statsLock(m_statsMutex);
    m_stats.droppedFrames++;
}

} // namespace utils
} // namespace av
