#include "mainwindowa.h"
#include "common.h"

#include <QApplication>
#include <QMenuBar>
#include <QStatusBar>

#include "ffmpeg_init.h"

#include "qimage_operation.h"
#include "qscreen.h"
#include "start_play_thread.h"

#include "../AvRecorder/ui/opengl_video_widget.h"

#if NDEBUG
#define AUTO_HIDE_PLAYCONTROL 1 // release version
#else
#define AUTO_HIDE_PLAYCONTROL 0
#endif

MainWindowA::MainWindowA(QWidget* parent)
    : QMainWindow(parent)
{
    m_playerController = new PlayerController;
    // 1. 菜单栏和主菜单
    m_menuBar = new QMenuBar(this);
    setMenuBar(m_menuBar);

    // 文件菜单
    m_menuFile = new QMenu(tr("文件"), this);
    m_menuBar->addMenu(m_menuFile);
    m_actionOpen = new QAction(tr("打开"), this);
    m_actionQuit = new QAction(tr("退出"), this);
    m_menuFile->addAction(m_actionOpen);
    m_menuFile->addSeparator();
    m_menuFile->addAction(m_actionQuit);
    connect(m_actionOpen, &QAction::triggered, this, &MainWindowA::on_actionOpen_triggered);
    connect(m_actionQuit, &QAction::triggered, this, &MainWindowA::on_actionQuit_triggered);

    // 最近文件菜单
    m_menuRecentFiles = new QMenu(tr("最近文件"), this);
    m_menuBar->addMenu(m_menuRecentFiles);

    // 播放列表菜单
    m_menuSavedPlaylist = new QMenu(tr("播放列表"), this);
    m_menuBar->addMenu(m_menuSavedPlaylist);

    // CV菜单
    m_menuCV = new QMenu(tr("图像处理"), this);
    m_menuBar->addMenu(m_menuCV);

    // 样式菜单
    m_menuStyle = new QMenu(tr("样式"), this);
    m_menuBar->addMenu(m_menuStyle);

    // 音频可视化菜单
    m_menuAudioVisualize = new QMenu(tr("音频可视化"), this);
    m_menuBar->addMenu(m_menuAudioVisualize);

    // 帮助菜单
    m_menuHelp = new QMenu(tr("帮助"), this);
    m_menuBar->addMenu(m_menuHelp);
    m_actionHelp = new QAction(tr("帮助"), this);
    m_actionAbout = new QAction(tr("关于"), this);
    m_actionAbout_QT = new QAction(tr("关于Qt"), this);
    m_menuHelp->addAction(m_actionHelp);
    m_menuHelp->addAction(m_actionAbout);
    m_menuHelp->addAction(m_actionAbout_QT);
    connect(m_actionHelp, &QAction::triggered, this, &MainWindowA::on_actionHelp_triggered);
    connect(m_actionAbout, &QAction::triggered, this, &MainWindowA::on_actionAbout_triggered);
    connect(m_actionAbout_QT, &QAction::triggered, qApp, &QApplication::aboutQt);

    // 2. 主控件和状态栏
    m_centralWidget = new QWidget(this);
    setCentralWidget(m_centralWidget);
    m_statusBar = new QStatusBar(this);
    setStatusBar(m_statusBar);

    // 3. 其他Action初始化
    m_actionStop = new QAction(tr("停止"), this);
    m_actionFullscreen = new QAction(tr("全屏"), this);
    m_actionFullscreen->setCheckable(true);
    m_actionHide_Play_Ctronl = new QAction(tr("隐藏控制栏"), this);
    m_actionHide_Play_Ctronl->setCheckable(true);
    m_actionAspect_Ratio = new QAction(tr("保持比例"), this);
    m_actionLoop_Play = new QAction(tr("循环播放"), this);
    m_actionLoop_Play->setCheckable(true);
    m_actionMedia_Info = new QAction(tr("媒体信息"), this);
    m_actionKeyboard_Usage = new QAction(tr("快捷键说明"), this);
    m_actionPlayList = new QAction(tr("播放列表窗口"), this);
    m_actionPlayList->setCheckable(true);
    m_actionOpenNetworkUrl = new QAction(tr("打开网络地址"), this);
    m_actionOriginalSize = new QAction(tr("原始大小"), this);
    m_actionHardware_decode = new QAction(tr("硬件解码"), this);
    m_actionHardware_decode->setCheckable(true);

    // 4. CV菜单Action
    m_actionGrayscale = new QAction(tr("灰度"), this);
    m_actionGrayscale->setCheckable(true);
    m_actionMirro = new QAction(tr("镜像"), this);
    m_actionMirro->setCheckable(true);
    m_actionTransform = new QAction(tr("变换"), this);
    m_actionTransform->setCheckable(true);
    m_menuCV->addAction(m_actionGrayscale);
    m_menuCV->addAction(m_actionMirro);
    m_menuCV->addAction(m_actionTransform);
    m_menuCV->addSeparator();

    m_actionRotate = new QAction(tr("旋转"), this);
    m_actionRotate->setCheckable(true);
    m_actionRepeat = new QAction(tr("重复"), this);
    m_actionRepeat->setCheckable(true);
    m_actionEqualizeHist = new QAction(tr("直方图均衡"), this);
    m_actionEqualizeHist->setCheckable(true);
    m_actionThreshold = new QAction(tr("二值化"), this);
    m_actionThreshold->setCheckable(true);
    m_actionThreshold_Adaptive = new QAction(tr("自适应阈值"), this);
    m_actionThreshold_Adaptive->setCheckable(true);
    m_actionReverse = new QAction(tr("反色"), this);
    m_actionReverse->setCheckable(true);
    m_actionColorReduce = new QAction(tr("色彩减少"), this);
    m_actionColorReduce->setCheckable(true);
    m_actionGamma = new QAction(tr("伽马"), this);
    m_actionGamma->setCheckable(true);
    m_actionContrastBright = new QAction(tr("对比度/亮度"), this);
    m_actionContrastBright->setCheckable(true);
    m_actionBlur = new QAction(tr("模糊"), this);
    m_actionBlur->setCheckable(true);
    m_actionCanny = new QAction(tr("Canny"), this);
    m_actionCanny->setCheckable(true);
    m_actionSobel = new QAction(tr("Sobel"), this);
    m_actionSobel->setCheckable(true);
    m_actionLaplacian = new QAction(tr("Laplacian"), this);
    m_actionLaplacian->setCheckable(true);
    m_actionScharr = new QAction(tr("Scharr"), this);
    m_actionScharr->setCheckable(true);
    m_actionPrewitt = new QAction(tr("Prewitt"), this);
    m_actionPrewitt->setCheckable(true);
    m_actionRemoveCV = new QAction(tr("移除选择"), this);
    m_actionRemoveCV->setCheckable(true);
    m_actionTest_CV = new QAction(tr("测试CV"), this);
    m_actionTest_CV->setCheckable(true);

    m_menuCV->addAction(m_actionRotate);
    m_menuCV->addAction(m_actionRepeat);
    m_menuCV->addAction(m_actionEqualizeHist);
    m_menuCV->addAction(m_actionThreshold);
    m_menuCV->addAction(m_actionThreshold_Adaptive);
    m_menuCV->addAction(m_actionReverse);
    m_menuCV->addAction(m_actionColorReduce);
    m_menuCV->addAction(m_actionGamma);
    m_menuCV->addAction(m_actionContrastBright);
    m_menuCV->addAction(m_actionBlur);
    m_menuCV->addAction(m_actionCanny);
    m_menuCV->addAction(m_actionSobel);
    m_menuCV->addAction(m_actionLaplacian);
    m_menuCV->addAction(m_actionScharr);
    m_menuCV->addAction(m_actionPrewitt);
    m_menuCV->addAction(m_actionRemoveCV);
    m_menuCV->addSeparator();
    m_menuCV->addAction(m_actionTest_CV);

    // 批量 connect CV 菜单下所有 QAction
    for (QAction* action : m_menuCV->actions()) {
        if (action && !action->isSeparator()) {
            connect(action, &QAction::toggled, this, &MainWindowA::onCvActionToggled);
        }
    }

    // 5. 音频可视化菜单Action
    m_actionLine = new QAction(tr("线形"), this);
    m_actionLine->setCheckable(true);
    m_actionBar = new QAction(tr("柱形"), this);
    m_actionBar->setCheckable(true);
    m_actionPie = new QAction(tr("饼形"), this);
    m_actionPie->setCheckable(true);
    m_actionSampling = new QAction(tr("采样"), this);
    m_actionSampling->setCheckable(true);
    m_actionFrequency = new QAction(tr("频率"), this);
    m_actionFrequency->setCheckable(true);

    m_menuAudioVisualize->addAction(m_actionLine);
    m_menuAudioVisualize->addAction(m_actionBar);
    m_menuAudioVisualize->addAction(m_actionPie);
    m_menuAudioVisualize->addSeparator();
    m_menuAudioVisualize->addAction(m_actionSampling);
    m_menuAudioVisualize->addAction(m_actionFrequency);

    // 6. 分组
    m_CvActsGroup = new QActionGroup(this);
    m_CvActsGroup->addAction(m_actionRotate);
    m_CvActsGroup->addAction(m_actionRepeat);
    m_CvActsGroup->addAction(m_actionEqualizeHist);
    m_CvActsGroup->addAction(m_actionThreshold);
    m_CvActsGroup->addAction(m_actionThreshold_Adaptive);
    m_CvActsGroup->addAction(m_actionReverse);
    m_CvActsGroup->addAction(m_actionColorReduce);
    m_CvActsGroup->addAction(m_actionGamma);
    m_CvActsGroup->addAction(m_actionContrastBright);
    m_CvActsGroup->addAction(m_actionCanny);
    m_CvActsGroup->addAction(m_actionBlur);
    m_CvActsGroup->addAction(m_actionSobel);
    m_CvActsGroup->addAction(m_actionLaplacian);
    m_CvActsGroup->addAction(m_actionScharr);
    m_CvActsGroup->addAction(m_actionPrewitt);
    m_CvActsGroup->addAction(m_actionRemoveCV);

    m_AVisualGrapicTypeActsGroup = new QActionGroup(this);
    m_AVisualGrapicTypeActsGroup->addAction(m_actionLine);
    m_AVisualGrapicTypeActsGroup->addAction(m_actionBar);
    m_AVisualGrapicTypeActsGroup->addAction(m_actionPie);

    m_AVisualTypeActsGroup = new QActionGroup(this);
    m_AVisualTypeActsGroup->addAction(m_actionSampling);
    m_AVisualTypeActsGroup->addAction(m_actionFrequency);

    // 7. 信号槽
    connect(m_actionSampling, &QAction::triggered, this, &MainWindowA::popup_audio_effect);
    connect(m_actionFrequency, &QAction::triggered, this, &MainWindowA::popup_audio_effect);
    connect(m_actionLine, &QAction::triggered, this, &MainWindowA::popup_audio_effect);
    connect(m_actionBar, &QAction::triggered, this, &MainWindowA::popup_audio_effect);
    connect(m_actionPie, &QAction::triggered, this, &MainWindowA::popup_audio_effect);

    // ... 其余Action信号槽如有也可补全 ...

    // 8. 继续原有初始化流程
    // setWindowFlags(windowFlags() | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint
    //                | Qt::WindowCloseButtonHint);

    // 新增：主布局，视频+控制条
    auto mainLayout = new QVBoxLayout(m_centralWidget);
    mainLayout->setContentsMargins(0, 0, 0, 0);
    mainLayout->setSpacing(0);
    create_video_label();
    create_play_control();
    create_audio_effect();

    if (m_video_widget)
        mainLayout->addWidget(m_video_widget.get(), 1);
    if (m_play_control_wnd)
        mainLayout->addWidget(m_play_control_wnd.get(), 0);

    mainLayout->addWidget(m_audio_effect_wnd.get(), 0);
    m_centralWidget->setLayout(mainLayout);

    setWindowTitle(tr("Video Player"));

    qApp->installEventFilter(this);
    setAcceptDrops(true);

#if AUTO_HIDE_PLAYCONTROL
    setMouseTracking(true);
    m_timer.setInterval(3 * 1000);
    m_timer.setSingleShot(false);
    connect(&m_timer, &QTimer::timeout, this, &MainWindowA::check_hide_play_control);
    m_timer.start();
#endif

    read_settings();
    update_menus();

#if !NDEBUG
    print_screen();
#endif

    resize(600, 600);

    connect(m_playerController,
            &PlayerController::startToPlaySignal,
            this,
            &MainWindowA::update_menus);
    connect(m_playerController, &PlayerController::frameReady, this, &MainWindowA::frameReady);

    connect(m_playerController, &PlayerController::audioData, this, &MainWindowA::audio_data);

    connect(m_playerController,
            &PlayerController::setPlayControlWnd,
            this,
            &MainWindowA::set_paly_control_wnd);
    connect(m_playerController,
            &PlayerController::updatePlayControlVolume,
            this,
            &MainWindowA::update_paly_control_volume);
    connect(m_playerController,
            &PlayerController::updatePlayControlStatus,
            this,
            &MainWindowA::update_paly_control_status);
    // 新增：连接UI相关信号
    connect(m_playerController, &PlayerController::showMessage, this, &MainWindowA::onShowMessage);
    connect(m_playerController,
            &PlayerController::requestFullscreen,
            this,
            &MainWindowA::onRequestFullscreen);
    connect(m_playerController,
            &PlayerController::requestHideStatusBar,
            this,
            &MainWindowA::onRequestHideStatusBar);
    connect(m_playerController,
            &PlayerController::updatePlayTime,
            this,
            &MainWindowA::update_play_time);
    //connect(m_playerController, &PlayerController::playSeek, this, &MainWindowA::play_seek);

    hide_play_control(false);

    m_playerController->startToPlay("C:/Users/zhuizhu/Videos/2.mp4");
}

MainWindowA::~MainWindowA()
{
    m_playerController->stopPlay();
    save_settings();
}

QScreen* MainWindowA::screen() const
{
    return QApplication::primaryScreen();
}

QRect MainWindowA::screen_rect() const
{
    //auto pScreen = screen();
    //auto scale = pScreen->devicePixelRatio();
    //return QRect(0, 0, rt.width() * scale, rt.height() * scale);
    return screen()->geometry();
}

qreal MainWindowA::screen_scale() const
{
    return screen()->devicePixelRatio();
}

QSize MainWindowA::display_video_size(AVCodecContext* pVideo) const
{
    auto scale = screen_scale(); //screen display scale
    if (pVideo && scale != 0)
        return QSize(pVideo->width / scale, pVideo->height / scale);

    return QSize(0, 0);
}

void MainWindowA::create_video_label()
{
    m_video_widget = std::make_unique<OpenGLVideoWidget>(centralWidget());
    // 不再单独设置布局，统一在 centralWidget 的主布局中管理
}

void MainWindowA::create_audio_effect()
{
    m_audio_effect_wnd = std::make_unique<AudioEffectGL>(centralWidget());
    m_audio_effect_wnd->setObjectName(QString::fromUtf8("audio_effect"));
    m_audio_effect_wnd->hide();

    // connect(m_audio_effect_wnd.get(), &AudioEffectGL::hiden, this, &MainWindowA::start_send_data);
    connect(m_audio_effect_wnd.get(),
            &AudioEffectGL::hiden,
            m_playerController,
            &PlayerController::startSendData);
}

void MainWindowA::show_audio_effect(bool bShow)
{
    if (!m_audio_effect_wnd)
        return;

    auto pt = frameGeometry().center() - m_audio_effect_wnd->rect().center();
    m_audio_effect_wnd->move(pt);
    m_audio_effect_wnd->paint_clear();

    if (bShow) {
        m_audio_effect_wnd->show();
    } else {
        m_audio_effect_wnd->hide();
    }
}

void MainWindowA::create_recentfiles_menu()
{
    for (int i = 0; i < MaxRecentFiles; ++i) {
        m_recentFileActs[i] = std::make_unique<QAction>(this);
        m_recentFileActs[i]->setVisible(false);
        connect(m_recentFileActs[i].get(), SIGNAL(triggered()), this, SLOT(open_recentFile()));
    }

    m_recentClear = std::make_unique<QAction>(this);
    m_recentClear->setText(tr("清除"));
    connect(m_recentClear.get(), SIGNAL(triggered()), this, SLOT(clear_recentfiles()));

    auto pMenu = m_menuRecentFiles;
    pMenu->clear();
    for (int i = 0; i < MaxRecentFiles; ++i)
        pMenu->addAction(m_recentFileActs[i].get());
    pMenu->addSeparator();
    pMenu->addAction(m_recentClear.get());

    update_recentfile_actions();
}

void MainWindowA::set_current_file(const QString& fileName)
{
    setWindowFilePath(fileName);

    auto files = m_settings.get_recentfiles().toStringList();
    files.removeAll(fileName);
    files.prepend(fileName);
    while (files.size() > MaxRecentFiles)
        files.removeLast();

    m_settings.set_recentfiles(files);

    update_recentfile_actions();
}

void MainWindowA::clear_recentfiles()
{
    auto files = m_settings.get_recentfiles().toStringList();
    files.clear();
    m_settings.set_recentfiles(files);

    update_recentfile_actions();
}

void MainWindowA::remove_recentfiles(const QString& fileName)
{
    auto files = m_settings.get_recentfiles().toStringList();
    files.removeAll(fileName);
    m_settings.set_recentfiles(files);

    update_recentfile_actions();
}

void MainWindowA::update_recentfile_actions()
{
    auto files = m_settings.get_recentfiles().toStringList();

    int numRecentFiles = qMin(files.size(), (int) MaxRecentFiles);

    m_menuRecentFiles->setEnabled(numRecentFiles > 0);

    for (int i = 0; i < numRecentFiles; ++i) {
        QString text = tr("%1 %2").arg(i + 1).arg(stripped_name(files[i]));
        m_recentFileActs[i]->setText(
            QApplication::translate("MainWindowA", text.toStdString().c_str(), nullptr));
        m_recentFileActs[i]->setData(files[i]);
        m_recentFileActs[i]->setVisible(true);
    }
    for (int j = numRecentFiles; j < MaxRecentFiles; ++j)
        m_recentFileActs[j]->setVisible(false);
}

QString MainWindowA::stripped_name(const QString& fullFileName) const
{
    return QFileInfo(fullFileName).fileName();
}

void MainWindowA::open_recentFile()
{
    if (auto action = qobject_cast<QAction*>(sender()))
        m_playerController->startToPlay(action->data().toString());
}

void MainWindowA::about_media_info()
{
    // if (!m_pVideoState)
    //     return;

    // auto pState = m_playerController->state();
    // if (!pState)
    //     return;

    // if (auto ic = pState->ic) {
    //     auto str = dump_format(ic, 0, pState->filename);
    //     show_msg_dlg(str, "Media information", "QLabel{min-width: 760px;}");
    // }
}

void MainWindowA::create_play_control()
{
    m_play_control_wnd = std::make_unique<PlayControlWnd>(m_playerController, this);
    m_play_control_wnd->setObjectName(QString::fromUtf8("play_control"));
    m_play_control_wnd->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed);
    // 不再 setGeometry
}

void MainWindowA::update_video_label()
{
    // 移除手动 resize，让布局自动管理
    // auto sizeCenter = centralWidget()->size();
    // if (auto pLabel = get_video_widget())
    //     pLabel->resize(sizeCenter.width(), sizeCenter.height());
}

void MainWindowA::show_msg_dlg(const QString& message,
                               const QString& windowTitle,
                               const QString& styleSheet)
{
    onShowMessage(message, windowTitle, styleSheet);
}

void MainWindowA::update_play_control()
{
    // if (auto pPlayControl = get_play_control()) {
    //     auto sizeCenter = centralWidget()->size();

    //     pPlayControl->resize(sizeCenter.width(), pPlayControl->size().height());

    //     auto frameGeoRt = frameGeometry();
    //     auto geoRt = geometry();

    //     // QPoint pt = ui->statusbar->pos();
    //     int borderH = frameGeoRt.height() - (geoRt.y() - frameGeoRt.y()) - geoRt.height();
    //     //int borderH = frameGeoRt.height() - geoRt.height();
    //     // int borderw = frameGeoRt.width() - geoRt.width();
    //     // int borderSelf = pPlayControl->frameGeometry().height() - (pPlayControl->geometry().y() - pPlayControl->frameGeometry().y()) - pPlayControl->geometry().height();

    //     //auto pt = geoRt.bottomLeft() - QPoint(0, szPlayControl.height() + borderH);
    //     auto pt = geoRt.bottomLeft() - QPoint(0, pPlayControl->size().height() - 1);
    //     pPlayControl->move(pt);
    // }
}

void MainWindowA::print_size() const
{
    auto rt = geometry();
    qDebug("geometry rt:(x:%d, y:%d, w:%d, h:%d)", rt.x(), rt.y(), rt.width(), rt.height());
    rt = frameGeometry();
    qDebug("frameGeometry rt:(x:%d, y:%d, w:%d, h:%d)", rt.x(), rt.y(), rt.width(), rt.height());

    auto size = this->size();
    qDebug("window size:(%d,%d)", size.width(), size.height());
    // 这里不再有ui->centralwidget，直接用m_centralWidget
    size = m_centralWidget->size();
    qDebug("centralwidget size:(%d,%d)", size.width(), size.height());
    // 菜单栏
    size = m_menuBar->size();
    qDebug("menubar size:(%d,%d)", size.width(), size.height());
    // 状态栏
    size = m_statusBar->size();
    qDebug("statusbar size:(%d,%d)", size.width(), size.height());
    // 菜单栏位置
    auto pt = m_menuBar->pos();
    qDebug("menuBar pt (x:%d, y:%d)", pt.x(), pt.y());
}

void MainWindowA::print_screen() const
{
    auto screen = QApplication::primaryScreen();
    auto rt = screen->availableGeometry();
    qDebug("availableGeometry rt (x:%d, y:%d, width:%d, height:%d)",
           rt.x(),
           rt.y(),
           rt.width(),
           rt.height());

    auto sz = screen->availableSize();
    qDebug("availableSize sz (width:%d, height:%d)", sz.width(), sz.height());

    sz = screen->size();
    qDebug("size sz (width:%d, height:%d)", sz.width(), sz.height());

    rt = screen->virtualGeometry();
    qDebug("virtualGeometry rt (x:%d, y:%d, width:%d, height:%d)",
           rt.x(),
           rt.y(),
           rt.width(),
           rt.height());

    sz = screen->virtualSize();
    qDebug("virtualSize sz (width:%d, height:%d)", sz.width(), sz.height());

    rt = screen->availableVirtualGeometry();
    qDebug("availableVirtualGeometry rt (x:%d, y:%d, width:%d, height:%d)",
           rt.x(),
           rt.y(),
           rt.width(),
           rt.height());

    sz = screen->availableVirtualSize();
    qDebug("availableVirtualSize sz (width:%d, height:%d)", sz.width(), sz.height());

    rt = screen->geometry();
    qDebug("geometry rt (x:%d, y:%d, width:%d, height:%d)", rt.x(), rt.y(), rt.width(), rt.height());

    auto depth = screen->depth();
    qDebug() << "depth :" << depth;

    auto ratio = screen->devicePixelRatio();
    qDebug() << "devicePixelRatio :" << ratio;

    auto dot_per_inch = screen->logicalDotsPerInch();
    qDebug() << "logicalDotsPerInch :" << dot_per_inch;

    auto x = screen->logicalDotsPerInchX();
    qDebug() << "logicalDotsPerInchX :" << x;

    auto y = screen->logicalDotsPerInchY();
    qDebug() << "logicalDotsPerInchY :" << y;

    auto str = screen->manufacturer();
    qDebug() << "manufacturer :" << str;

    str = screen->model();
    qDebug() << "model :" << str;

    str = screen->name();
    qDebug() << "name :" << str;

    str = screen->serialNumber();
    qDebug() << "serialNumber :" << str;

    auto o = screen->nativeOrientation();
    qDebug() << "nativeOrientation :" << o;

    o = screen->orientation();
    qDebug() << "orientation :" << o;

    o = screen->primaryOrientation();
    qDebug() << "primaryOrientation :" << o;

    auto ph_d = screen->physicalDotsPerInch();
    qDebug() << "physicalDotsPerInch :" << ph_d;

    ph_d = screen->physicalDotsPerInchX();
    qDebug() << "physicalDotsPerInchX :" << ph_d;

    ph_d = screen->physicalDotsPerInchY();
    qDebug() << "physicalDotsPerInchY :" << ph_d;

    auto sz_f = screen->physicalSize();
    qDebug() << "physicalSize :" << sz_f;

    auto fr = screen->refreshRate();
    qDebug() << "refreshRate :" << fr;
}

void MainWindowA::resizeEvent(QResizeEvent* event)
{
    update_video_label();
    update_play_control();

    QMainWindow::resizeEvent(event);
}

void MainWindowA::moveEvent(QMoveEvent* event)
{
    update_play_control();
    QMainWindow::moveEvent(event);
}

void MainWindowA::keyPressEvent(QKeyEvent* event)
{
    qDebug() << "Mainwindow key event, event:" << event->text() << "key:" << event->key()
             << "key_str:" << QKeySequence(event->key()).toString();

    switch (event->key()) {
    case Qt::Key_Space:  // pause/continue
    case Qt::Key_Up:     // volume up
    case Qt::Key_Down:   // volume down
    case Qt::Key_Left:   // play back
    case Qt::Key_Right:  // play forward
    case Qt::Key_M:      // mute
    case Qt::Key_Comma:  // speed down
    case Qt::Key_Period: // speed up
        play_control_key((Qt::Key) event->key());
        break;

    case Qt::Key_A: // aspect ratio
        on_actionAspect_Ratio_triggered();
        break;

    case Qt::Key_O: // keep orginal size
        on_actionOriginalSize_triggered();
        break;

    case Qt::Key_L: // show play list wnd
    {
        show_playlist();
        m_actionPlayList->setChecked(true);
    } break;

    case Qt::Key_F: // full screen
    {
        bool bFullscreen = label_fullscreen();
        show_fullscreen(!bFullscreen);
        m_actionFullscreen->setChecked(!bFullscreen);
    } break;

    case Qt::Key_Escape: {
        show_fullscreen(false);
        m_actionFullscreen->setChecked(false);
    } break;

    case Qt::Key_H:
        on_actionKeyboard_Usage_triggered();
        break;

    default:
        qDebug("Not handled key event, key:%s(%d) pressed!\n",
               qUtf8Printable(event->text()),
               event->key());
        QWidget::keyPressEvent(event);
        break;
    }
}

bool MainWindowA::eventFilter(QObject* obj, QEvent* event)
{
    if (event->type() == QEvent::MouseMove) {
        auto mouseEvent = static_cast<QMouseEvent*>(event);
        // displayStatusMessage(QString("Mouse move
        // (%1,%2)").arg(mouseEvent->pos().x()).arg(mouseEvent->pos().y()));

        check_hide_menubar(mouseEvent->pos());

#if AUTO_HIDE_PLAYCONTROL
        if (!(m_actionHide_Play_Ctronl->isChecked() || label_fullscreen())) {
            if (cursor_in_window(get_play_control())) {
                m_timer.stop();
                auto_hide_play_control(false);
            } else {
                m_timer.start();
            }
        }

        hide_cursor(false);
        setCursor(Qt::ArrowCursor);
#endif
    }
    return QMainWindow::eventFilter(obj, event);
}

void MainWindowA::dropEvent(QDropEvent* event)
{
    auto mimeData = event->mimeData();

    if (!mimeData->hasUrls())
        return;

    if (auto urlList = mimeData->urls(); urlList.size() > 0)
        m_playerController->startToPlay(urlList.at(0).toLocalFile());
}

void MainWindowA::dragEnterEvent(QDragEnterEvent* event)
{
    if (auto mimeData = event->mimeData(); mimeData->hasUrls())
        event->acceptProposedAction();
    event->accept();
}

void MainWindowA::check_hide_menubar(const QPoint& pt)
{
    if (isFullScreen())
        hide_menubar(pt.y() > menuBar()->geometry().height());
}

void MainWindowA::check_hide_play_control()
{
    if (!m_playerController->isPlaying())
        return;

    if (!isFullScreen() && cursor_in_window(get_play_control())) {
        qDebug() << "Cursor is in PlayControl window, don't hide it.";
        return;
    }

    auto_hide_play_control();
    hide_cursor();
}

void MainWindowA::auto_hide_play_control(bool bHide)
{
    if (!get_play_control())
        return;

    if (!m_playerController->state())
        return;

    if (m_actionHide_Play_Ctronl->isChecked())
        return;

    hide_play_control(bHide);
}

void MainWindowA::on_actionOpen_triggered()
{
    const QStringList filters(
        {"Videos (*.mp4 *.avi *.mkv)", "Audios (*.mp3 *.wav *.wma)", "Any files (*)"});

    QFileDialog dialog(this);
    dialog.setFileMode(QFileDialog::ExistingFile);
    // dialog.setNameFilter(tr("Videos (*.mp4 *.avi *.mp3)"));
    dialog.setNameFilters(filters);
    dialog.setViewMode(QFileDialog::List);

    if (dialog.exec()) {
        m_playerController->startToPlay(dialog.selectedFiles()[0]);
    }
}

void MainWindowA::on_actionAspect_Ratio_triggered() {}

void MainWindowA::on_actionQuit_triggered()
{
    QMainWindow::close();
}

void MainWindowA::on_actionHelp_triggered() {}

void MainWindowA::on_actionStop_triggered()
{
    m_playerController->stopPlay();
}

void MainWindowA::on_actionHide_Play_Ctronl_triggered()
{
    hide_play_control(m_actionHide_Play_Ctronl->isChecked());
}

void MainWindowA::on_actionFullscreen_triggered()
{
    show_fullscreen(m_actionFullscreen->isChecked());
}

void MainWindowA::on_actionLoop_Play_triggered()
{
    if (auto pState = m_playerController->state())
        pState->loop = int(m_actionLoop_Play->isChecked());
}

void MainWindowA::on_actionMedia_Info_triggered()
{
    if (m_playerController->isPlaying())
        about_media_info();
}

void MainWindowA::on_actionKeyboard_Usage_triggered()
{
    QString str;
    QString indent = "		";
    str += "A" + indent + "Video aspect ratio\n";
    str += "F" + indent + "Fulllscreen/Unfullscreen\n";
    str += "H" + indent + "Show help\n";
    str += "L" + indent + "Show playlist\n";
    str += "M" + indent + "Mute/Unmute\n";
    str += "O" + indent + "Keep video original size\n";
    str += "Space" + indent + "Pause/Play\n";
    str += "Up" + indent + "Volume up\n";
    str += "Down" + indent + "Volume down\n";
    str += "Left" + indent + "Play back\n";
    str += "Right" + indent + "Play forward\n";
    str += "<" + indent + "Speed down\n";
    str += ">" + indent + "Speed up\n";

    show_msg_dlg(str, "Keyboard Control");
}

void MainWindowA::set_audio_effect_format(const BarHelper::VisualFormat& fmt)
{
    if (m_audio_effect_wnd)
        m_audio_effect_wnd->set_draw_fmt(fmt);
}

void MainWindowA::popup_audio_effect()
{
    if (m_playerController->isPlaying()) {
        BarHelper::VisualFormat fmt;
        get_avisual_format(fmt);
        set_audio_effect_format(fmt);
        show_audio_effect();
        m_playerController->startSendData();
    }
}

void MainWindowA::center_window(QRect screen_rec)
{
    auto x = (screen_rec.width() - width()) / 2;
    auto y = (screen_rec.height() - height()) / 2;
    move(x, y);
    show();
}

void MainWindowA::show_fullscreen(bool bFullscreen)
{
    onRequestFullscreen(bFullscreen);
}

bool MainWindowA::label_fullscreen()
{
    if (auto pLabel = get_video_widget())
        return pLabel->isFullScreen();
    return false;
}

void MainWindowA::on_actionOriginalSize_triggered()
{
    // if (!m_pVideoState)
    //     return;

    // auto pVideoCtx = m_pVideoState->get_contex(AVMEDIA_TYPE_VIDEO);
    // auto pLabel = get_video_widget();
    // if (!pVideoCtx || !pLabel)
    //     return;

    // auto sizeLabel = pLabel->size();
    // auto sz = size();

    // auto video_sz = display_video_size(pVideoCtx);
    // int new_width = video_sz.width();
    // int new_height = video_sz.height();

    // if (new_width < minimumWidth()) {
    //     new_height = minimumWidth() * new_height / new_width;
    //     new_width = minimumWidth();
    // }

    // if (new_height < minimumHeight()) {
    //     new_width = minimumHeight() * new_width / new_height;
    //     new_height = minimumHeight();
    // }

    // int w_change = new_width - sizeLabel.width();
    // int h_change = new_height - sizeLabel.height();

    // sz += QSize(w_change, h_change);
    // resize_window(sz);
}

void MainWindowA::hide_play_control(bool bHide)
{
    // if (auto pPlayControl = get_play_control()) {
    //     // pPlayControl->setVisible(true);
    //     // pPlayControl->setDisabled(false);
    //     if (pPlayControl->isVisible() == bHide) {
    //         pPlayControl->setVisible(!bHide);
    //     }
    // }
}

void MainWindowA::set_paly_control_wnd(bool set)
{
    auto pPlayControl = get_play_control();
    if (!pPlayControl)
        return;

    if (set) {
        auto pState = m_playerController->state();
        if (!pState)
            return;

        if (auto ic = pState->ic) {
            int64_t hours, mins, secs, us;
            get_duration_time(ic->duration, hours, mins, secs, us);
            pPlayControl->set_total_time(hours, mins, secs);
        }
    } else {
        pPlayControl->clear_all();
    }
}

void MainWindowA::set_volume_updown(bool bUp, float unit)
{
    auto volume = m_playerController->deviceVolume();
    auto n_volume = volume;
    if (bUp) {
        n_volume += unit;
    } else {
        n_volume -= unit;
    }

    if (n_volume > 1.0 || n_volume < 0) {
        QApplication::beep();
    }

    n_volume = n_volume > 1.0 ? 1.0 : n_volume;
    n_volume = n_volume < 0 ? 0 : n_volume;

    set_volume(int(n_volume * 100));
    update_paly_control_volume();
}

void MainWindowA::update_paly_control_volume()
{
    if (auto pPlayControl = get_play_control())
        pPlayControl->set_volume_slider(m_playerController->deviceVolume());
}

void MainWindowA::update_paly_control_muted()
{
    if (auto pPlayControl = get_play_control()) {
        if (auto pState = m_playerController->state())
            pPlayControl->volume_muted(pState->muted);
    }
}

void MainWindowA::update_paly_control_status()
{
    if (auto pPlayControl = get_play_control()) {
        if (auto pState = m_playerController->state())
            pPlayControl->update_btn_play(!!pState->paused);
    }
}

void MainWindowA::update_play_time()
{
    if (auto pPlayControl = get_play_control()) {
        // pPlayControl->setVisible(true);
        // pPlayControl->resize(800, 200);
        // pPlayControl->show();
        if (auto pState = m_playerController->state())
            pPlayControl->update_play_time(pState->audio_clock);
    }
}


void MainWindowA::play_seek()
{
    if (auto pPlayControl = get_play_control()) {
        auto maxValue = pPlayControl->get_progress_slider_max();
        auto total_time = pPlayControl->get_total_time();
        auto value = pPlayControl->get_progress_slider_value();

        double seek_time = 0;
        if (maxValue > 0)
            seek_time = value * total_time * 1.0 / maxValue;

        qDebug() << "val:" << value << ",maxVal:" << maxValue << ",total time" << total_time
                 << ",seek time:" << seek_time;
        m_playerController->videoSeek(seek_time);
    }

    update_paly_control_status();
}

void MainWindowA::play_mute(bool mute)
{
    auto pState = m_playerController->state();
    if (pState)
        toggle_mute(pState, mute);
}

void MainWindowA::set_volume(int volume)
{
    auto pPlayControl = get_play_control();
    if (!pPlayControl)
        return;

    auto max_val = pPlayControl->get_volum_slider_max();
    auto vol = volume * 1.0 / max_val;
    m_playerController->setDeviceVolume(vol);

    volume_settings(true, vol);
}

void MainWindowA::set_play_speed()
{
    auto pPlayControl = get_play_control();
    if (!pPlayControl)
        return;

    auto speed = pPlayControl->get_speed();

    qDebug("set_play_spped, speed control changed, speed:%d", speed);
    if (m_playerController) {
        if (auto pState = m_playerController->state()) {
#if USE_AVFILTER_AUDIO
            set_audio_playspeed(pState, speed);
#endif
        }
    }
}

void MainWindowA::play_speed_adjust(bool up)
{
    if (auto pPlayControl = get_play_control())
        pPlayControl->speed_adjust(up);

    set_play_speed();
}

void MainWindowA::hide_statusbar(bool bHide)
{
    onRequestHideStatusBar(bHide);
}

void MainWindowA::hide_menubar(bool bHide)
{
    menuBar()->setVisible(!bHide);

    // qDebug("is full screen:%d, menu is visible:%d", isFullScreen(), bVisible);
    if (isFullScreen()) {
        centralWidget()->resize(centralWidget()->size());
    }

    update_play_control();
}

void MainWindowA::on_actionAbout_triggered() {}

void MainWindowA::play_failed(const QString& file)
{
    show_msg_dlg(QString("File play failed, file: %1").arg(toNativePath(file)));
}

void MainWindowA::play_start_seek()
{
    play_seek();
    m_playerController->pausePlay();
}

void MainWindowA::play_control_key(Qt::Key key)
{
    if (!m_playerController)
        return;

    auto pState = m_playerController->state();
    if (!pState)
        return;

    switch (key) {
    case Qt::Key_Space: // pause/continue
        m_playerController->pausePlay();
        break;

    case Qt::Key_M:
        toggle_mute(pState, !pState->muted);
        update_paly_control_muted();
        break;

    case Qt::Key_Up: // volume
        set_volume_updown(true);
        break;

    case Qt::Key_Down: // volume
        set_volume_updown(false);
        break;

    case Qt::Key_Left:
        m_playerController->playSeekPre();
        break;

    case Qt::Key_Right:
        m_playerController->playSeekNext();
        break;

    case Qt::Key_Comma:
        play_speed_adjust(false);
        break;

    case Qt::Key_Period:
        play_speed_adjust(true);
        break;

    default:
        qDebug("key:(%d) pressed, not handled!\n", key);
        break;
    }
}

void MainWindowA::frameReady(AVFrame* frame)
{
    // 添加空指针检查和frame有效性检查
    if (!frame || !frame->data[0] || frame->width <= 0 || frame->height <= 0) {
        return;
    }
    
    auto widget = get_video_widget();
    if (widget) {
        widget->Render(frame);
    }
}

void MainWindowA::subtitle_ready(const QString& text)
{
    set_subtitle(text);
}

void MainWindowA::set_subtitle(const QString& str)
{
    m_subtitle = str;
    qDebug() << "subtitle received:" << m_subtitle;
}

void MainWindowA::clear_subtitle_str()
{
    set_subtitle("");
}

void MainWindowA::displayStatusMessage(const QString& message)
{
    int timeout = 0; // 5000: 5 second timeout
    if (auto bar = statusBar())
        bar->showMessage(message, timeout);
}

void MainWindowA::print_decodeContext(const AVCodecContext* pDecodeCtx, bool bVideo) const
{
    if (!pDecodeCtx)
        return;

    if (bVideo) {
        qInfo("video codec_name: %s", pDecodeCtx->codec->name);
        qInfo("codec_type: %d, codec_id: %d, codec_tag: %d",
              pDecodeCtx->codec_type,
              pDecodeCtx->codec_id,
              pDecodeCtx->codec_tag);
        qInfo("width: %d, height: %d, codec_tag: %d", pDecodeCtx->width, pDecodeCtx->height);
    } else {
        qInfo("audio codec_name: %s", pDecodeCtx->codec->name);
        qInfo("codec_type: %d, codec_id: %d, codec_tag: %d",
              pDecodeCtx->codec_type,
              pDecodeCtx->codec_id,
              pDecodeCtx->codec_tag);
        qInfo("sample_rate: %d, channels: %d, sample_fmt: %d",
              pDecodeCtx->sample_rate,
              pDecodeCtx->ch_layout.nb_channels,
              pDecodeCtx->sample_fmt);
        qInfo("frame_size: %d, frame_number: %d, block_align: %d",
              pDecodeCtx->frame_size,
              pDecodeCtx->frame_num,
              pDecodeCtx->block_align);
    }
}

void MainWindowA::save_settings()
{
    auto res = m_actionHide_Play_Ctronl->isChecked();
    m_settings.set_general("hidePlayContrl", int(res));
    res = m_actionFullscreen->isChecked();
    m_settings.set_general("fullScreen", int(res));

    res = m_actionHardware_decode->isChecked();
    m_settings.set_general("openDXVA2", int(res));
    res = m_actionLoop_Play->isChecked();
    m_settings.set_general("loopPlay", int(res));

    m_settings.set_general("style", get_selected_style());

    m_settings.set_info("software", "Video player");
    //m_settings.set_info("version", PLAYER_VERSION);
    m_settings.set_info("author", "Steven Huang");
}

void MainWindowA::read_settings()
{
    int value;
    auto values = m_settings.get_general("hidePlayContrl");
    if (values.isValid()) {
        value = values.toInt();
        m_actionHide_Play_Ctronl->setChecked(!!value);
        hide_play_control(value);
    }

    values = m_settings.get_general("fullScreen");
    if (values.isValid()) {
        value = values.toInt();
        m_actionFullscreen->setChecked(!!value);
        show_fullscreen(value);
    }

    values = m_settings.get_general("openDXVA2");
    if (values.isValid()) {
        value = values.toInt();
        m_actionHardware_decode->setChecked(!!value);
    }

    values = m_settings.get_general("loopPlay");
    if (values.isValid()) {
        value = values.toInt();
        m_actionLoop_Play->setChecked(!!value);
    }
}

float MainWindowA::volume_settings(bool set, float vol)
{
    if (set) {
        m_settings.set_general("volume", QString::number(float(vol), 'f', 1));
    } else {
        auto value = 0.2f; // default sound volume
        auto values = m_settings.get_general("volume");
        if (values.isValid())
            value = values.toFloat();
        return value;
    }
    return 0;
}

QString MainWindowA::get_selected_style() const
{
    auto pMenu = m_menuStyle;
    for (auto action : pMenu->actions()) {
        if (!(action->isSeparator() || action->menu())) {
            qDebug("action: %s", qUtf8Printable(action->text()));
            if (action->isChecked())
                return action->data().toString();
        }
    }
    return QString("");
}

void MainWindowA::set_style_action(const QString& style)
{
    auto pMenu = m_menuStyle;
    for (auto action : pMenu->actions()) {
        if (!(action->isSeparator() || action->menu())) {
            if (action->data().toString() == style)
                action->setChecked(true);
        }
    }
}

void MainWindowA::audio_data(const AudioData& data)
{
    if (m_audio_effect_wnd)
        m_audio_effect_wnd->paint_data(data);
}

void MainWindowA::update_menus()
{
    qDebug() << "update_menus: " << m_playerController->isPlaying();
    enable_menus(m_playerController->isPlaying());
    enable_v_menus(m_playerController->playingHasVideo());
    enable_a_menus(m_playerController->playingHasAudio());
}

void MainWindowA::enable_menus(bool enable)
{
    m_actionStop->setEnabled(enable);
    m_actionMedia_Info->setEnabled(enable);
}

void MainWindowA::enable_v_menus(bool enable)
{
    m_actionAspect_Ratio->setEnabled(enable);
    m_actionOriginalSize->setEnabled(enable);
    m_actionHardware_decode->setEnabled(enable);

    for (auto& pAction : m_menuCV->actions()) {
        if (pAction)
            pAction->setEnabled(enable);
    }
}

void MainWindowA::enable_a_menus(bool enable)
{
    m_menuAudioVisualize->setEnabled(enable);
}

bool MainWindowA::get_avisual_format(BarHelper::VisualFormat& fmt) const
{
    if (m_actionLine->isChecked()) {
        fmt.gType = BarHelper::e_GtLine;
    } else if (m_actionBar->isChecked()) {
        fmt.gType = BarHelper::e_GtBar;
    } else if (m_actionPie->isChecked()) {
        fmt.gType = BarHelper::e_GtPie;
    }

    if (m_actionSampling->isChecked()) {
        fmt.vType = BarHelper::e_VtSampleing;
    } else if (m_actionFrequency->isChecked()) {
        fmt.vType = BarHelper::e_VtFrequency;
    }

    return true;
}

void MainWindowA::create_playlist_wnd()
{
    m_playListWnd = std::make_unique<PlayListWnd>(this);
    connect(m_playListWnd.get(),
            &PlayListWnd::play_file,
            m_playerController,
            &PlayerController::startToPlay);
    // connect(m_playListWnd.get(), &PlayListWnd::save_playlist_signal, this, &MainWindowA::save_playlist);
    connect(m_playListWnd.get(), &PlayListWnd::hiden, this, &MainWindowA::playlist_hiden);
    connect(m_playListWnd.get(),
            &PlayListWnd::playlist_file_saved,
            this,
            &MainWindowA::playlist_file_saved);
}

void MainWindowA::on_actionPlayList_triggered()
{
    show_playlist(m_actionPlayList->isChecked());
}

void MainWindowA::show_playlist(bool show)
{
    if (!m_playListWnd)
        return;

    if (show) {
        m_playListWnd->show();
        m_playListWnd->set_cur_palyingfile();
    } else {
        m_playListWnd->hide();
    }
}

void MainWindowA::playlist_hiden()
{
    m_actionPlayList->setChecked(false);
}

void MainWindowA::add_to_playlist(const QString& file)
{
    if (m_playListWnd)
        m_playListWnd->add_file(file);
}

QString MainWindowA::get_playingfile() const
{
    if (m_playerController->isPlaying())
        return m_videoFile;
    return QString("");
}

void MainWindowA::on_actionOpenNetworkUrl_triggered()
{
    NetworkUrlDlg dialog(this);

    if (dialog.exec() == QDialog::Accepted) {
        if (auto url = dialog.get_url(); !url.isEmpty()) {
            m_playerController->startToPlay(url);
        } else {
            show_msg_dlg("Please input a valid youtube url. ");
        }
    }
}

void MainWindowA::hide_cursor(bool bHide)
{
    // if (bHide) {
    //     QApplication::setOverrideCursor(Qt::BlankCursor);
    // } else {
    //     QGuiApplication::restoreOverrideCursor();
    // }
}

bool MainWindowA::cursor_in_window(QWidget* pWnd)
{
    if (!pWnd)
        return false;

    auto rt = pWnd->rect();
    return rt.contains(pWnd->mapFromGlobal(QCursor::pos()));
}

void MainWindowA::create_savedPlaylists_menu()
{
    for (int i = 0; i < MaxPlaylist; ++i) {
        m_savedPlaylists[i] = std::make_unique<QAction>(this);
        m_savedPlaylists[i]->setVisible(false);
        connect(m_savedPlaylists[i].get(), SIGNAL(triggered()), this, SLOT(open_playlist()));
    }

    m_PlaylistsClear = std::make_unique<QAction>(this);
    m_PlaylistsClear->setText(tr("清除"));
    connect(m_PlaylistsClear.get(), SIGNAL(triggered()), this, SLOT(clear_savedPlaylists()));

    auto pMenu = m_menuSavedPlaylist;
    pMenu->clear();
    for (int i = 0; i < MaxPlaylist; ++i)
        pMenu->addAction(m_savedPlaylists[i].get());
    pMenu->addSeparator();
    pMenu->addAction(m_PlaylistsClear.get());

    update_savedPlaylists_actions();
}

void MainWindowA::remove_playlist_file(const QString& fileName)
{
    auto files = m_settings.get_savedplaylists().toStringList();
    files.removeAll(fileName);
    m_settings.set_savedplaylists(files);

    update_savedPlaylists_actions();
}

void MainWindowA::update_savedPlaylists_actions()
{
    auto files = m_settings.get_savedplaylists().toStringList();

    int num = qMin(files.size(), (int) MaxPlaylist);

    m_menuSavedPlaylist->setEnabled(num > 0);

    for (int i = 0; i < num; ++i) {
        QString text = tr("%1 %2").arg(i + 1).arg(stripped_name(files[i]));
        m_savedPlaylists[i]->setText(
            QApplication::translate("MainWindowA", text.toStdString().c_str(), nullptr));
        m_savedPlaylists[i]->setData(files[i]);
        m_savedPlaylists[i]->setVisible(true);
    }

    for (int j = num; j < MaxPlaylist; ++j)
        m_savedPlaylists[j]->setVisible(false);
}

void MainWindowA::clear_savedPlaylists()
{
    auto files = m_settings.get_savedplaylists().toStringList();

    for (const auto& i : files) {
        QFile file(i);
        file.remove();
    }

    files.clear();
    m_settings.set_savedplaylists(files);

    update_savedPlaylists_actions();
}

void MainWindowA::open_playlist()
{
    if (!m_playListWnd)
        return;

    auto action = qobject_cast<QAction*>(sender());
    if (!action)
        return;

    auto file = action->data().toString();

    QStringList files;
    if (read_playlist(file, files)) {
        m_playListWnd->update_files(files);
        show_playlist();
        m_actionPlayList->setChecked(true);
    } else {
        remove_playlist_file(file);
    }
}

void MainWindowA::playlist_file_saved(const QString& file)
{
    auto files = m_settings.get_savedplaylists().toStringList();
    files.removeAll(file);
    files.prepend(file);

    if (files.size() > MaxPlaylist) {
        show_msg_dlg(QString("You can only save %1 playlist files!").arg(MaxPlaylist));
    }

    while (files.size() > MaxPlaylist)
        files.removeLast();

    m_settings.set_savedplaylists(files);
    update_savedPlaylists_actions();
}

bool MainWindowA::read_playlist(const QString& playlist_file, QStringList& files) const
{
    QFile file(playlist_file);
    if (file.open(QIODevice::ReadOnly)) {
        QTextStream stream(&file);
        stream.setCodec("UTF-8");

        files = stream.readAll().split(PLAYLIST_SEPERATE_CHAR);
        files.removeAll(QString(""));
        file.close();
        return true;
    }
    return false;
}

// ========== CV菜单Action统一处理槽 ==========
void MainWindowA::onCvActionToggled()
{
    if (!m_video_widget)
        return;
    // 灰度
    m_video_widget->setGray(m_actionGrayscale && m_actionGrayscale->isChecked());
    // 二值化
    m_video_widget->setThreshold(m_actionThreshold && m_actionThreshold->isChecked(), 0.5f);
    // 模糊
    m_video_widget->setBlur(m_actionBlur && m_actionBlur->isChecked(), 1.0f);
    // 反色
    m_video_widget->setReverse(m_actionReverse && m_actionReverse->isChecked());
    // 色彩减少
    m_video_widget->setColorReduce(m_actionColorReduce && m_actionColorReduce->isChecked(), 8);
    // 伽马
    m_video_widget->setGamma(m_actionGamma && m_actionGamma->isChecked(), 1.2f);
    // 对比度/亮度
    m_video_widget->setContrastBright(m_actionContrastBright && m_actionContrastBright->isChecked(),
                                      1.2f,
                                      0.1f);
    // 镜像
    m_video_widget->setMirror(m_actionMirro && m_actionMirro->isChecked());
    // 其它特效可继续扩展
}

// 新增槽函数实现
void MainWindowA::onShowMessage(const QString& message,
                                const QString& windowTitle,
                                const QString& styleSheet)
{
    QMessageBox msgBox;
    msgBox.setText(message);
    msgBox.setWindowTitle(windowTitle);
    msgBox.setStyleSheet(styleSheet);
    msgBox.show();
    msgBox.move(frameGeometry().center() - msgBox.rect().center());
    msgBox.setWindowFlags(msgBox.windowFlags() | Qt::Dialog);
    msgBox.setModal(true);
    msgBox.exec();
}

void MainWindowA::onRequestFullscreen(bool bFullscreen)
{
    if (bFullscreen) {
        showFullScreen();
    } else {
        showNormal();
        update_video_label();
    }
    hide_cursor(bFullscreen);
}

void MainWindowA::onRequestHideStatusBar(bool bHide)
{
    statusBar()->setVisible(!bHide);
    auto sz_status = statusBar()->size();
    if (isFullScreen()) {
        centralWidget()->resize(centralWidget()->size());
    } else {
        auto sz = size();
        if (statusBar()->isVisible()) {
            sz += QSize(0, sz_status.height());
        } else {
            sz -= QSize(0, sz_status.height());
        }
        resize(sz);
    }
}
