// SPDX-FileCopyrightText: 2019 - 2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#include "mainwindow.h"
#include "displaymanager.h"
#include "constants.h"

#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
#include <QKeyEvent>
#include <QScrollBar>
#include <QScreen>
#include <QPropertyAnimation>
#include <QSequentialAnimationGroup>

#include <DFontSizeManager>
#include <DGuiApplicationHelper>
#include <DPlatformTheme>
#include <DIcon>
#include <DDciIcon>
#include <DConfig>
#include <DFloatingMessage>

#include "messagemanager.h"
#include "itemwidget.h"

#define DOCK_TOP        0
#define DOCK_RIGHT      1
#define DOCK_BOTTOM     2
#define DOCK_LEFT       3

#define MONITOR_SERVICE "org.deepin.dde.XEventMonitor1"

const QString AppearanceService = QStringLiteral("org.deepin.dde.Appearance1");
const QString AppearancePath = QStringLiteral("/org/deepin/dde/Appearance1");
const QString AppearanceInterface = QStringLiteral("org.deepin.dde.Appearance1");

static QColor outerBorderColor = QColor(0, 0, 0, static_cast<int>(0.15 * 255));
static QColor innerBorderColor = QColor(255, 255, 255, static_cast<int>(0.2 * 255));
#define ALPHA_OFFSET 10

MainWindow::MainWindow(QWidget *parent)
    : DBlurEffectWidget(parent)
    , m_displayInter(new DBusDisplay("org.deepin.dde.Display1", "/org/deepin/dde/Display1", QDBusConnection::sessionBus(), this))
    , m_daemonDockInter(new DBusDaemonDock("org.deepin.dde.daemon.Dock1", "/org/deepin/dde/daemon/Dock1", QDBusConnection::sessionBus(), this))
    , m_appearanceInter(new DDBusInterface(AppearanceService, AppearancePath, AppearanceInterface, QDBusConnection::sessionBus(), this))
    , m_regionMonitor(nullptr)
    , m_content(new DWidget(parent))
    , m_listview(new ListView(this))
    , m_model(new ClipboardModel(m_listview))
    , m_itemDelegate(new ItemDelegate(m_listview))
    , m_placeholderWidget(new DWidget(this))
    , m_placeholderIcon(new DIconButton(this))
    , m_placeholderLabel(new DLabel(this))
    , m_tipsWidget(nullptr)
    , m_xAni(new QPropertyAnimation(this))
    , m_widthAni(new QPropertyAnimation(this))
    , m_aniGroup(new QSequentialAnimationGroup(this))
    , m_wmHelper(DWindowManagerHelper::instance())
    , m_trickTimer(new QTimer)
    , m_windowHandle(new DPlatformWindowHandle(this, this))
    , m_isWayland(qGuiApp->platformName() == QStringLiteral("wayland"))
    , m_currentMargins(WindowMargin, WindowMargin, WindowMargin, WindowMargin)
{
    initConfig();
    initUI();
    initAni();
    initConnect();

    geometryChanged();
    CompositeChanged();
    registerMonitor();

    installEventFilter(this);
}

MainWindow::~MainWindow()
{

}

double MainWindow::opacity()
{
    return qvariant_cast<double>(m_appearanceInter->property("Opacity"));
}

void MainWindow::Toggle()
{
    if (m_aniGroup->state() == QAbstractAnimation::Running)
        return;

    if (isVisible()) {
        hideAni();
    } else {
        showAni();
    }
}

void MainWindow::geometryChanged()
{
    // Wayland layer-shell implementation
    auto layerShellWnd = ds::DLayerShellWindow::get(windowHandle());
    QMargins margins(WindowMargin, WindowMargin, WindowMargin, WindowMargin);
    auto dockGeometry = m_daemonDockInter->frontendWindowRect();
    // frontendWindowRect is physical screen rect, we need to convert it to logical screen rect.
    dockGeometry = QRect(
        dockGeometry.x() / qApp->devicePixelRatio(),
        dockGeometry.y() / qApp->devicePixelRatio(),
        dockGeometry.width() / qApp->devicePixelRatio(),
        dockGeometry.height() / qApp->devicePixelRatio()
    );

    // dock not hide and in current screen
    if (!m_isWayland && m_daemonDockInter->hideState() != 2 && (window() && window()->screen()->geometry().contains(dockGeometry))) {
        switch (m_daemonDockInter->position()) {
            case DOCK_TOP: margins.setTop(dockGeometry.height() + WindowMargin); break;
            case DOCK_BOTTOM: margins.setBottom(dockGeometry.height() + WindowMargin); break;
            case DOCK_LEFT: break;
            case DOCK_RIGHT: margins.setRight(dockGeometry.width() + WindowMargin); break;
        }
    }

    layerShellWnd->setRightMargin(margins.right());
    layerShellWnd->setBottomMargin(margins.bottom());
    layerShellWnd->setTopMargin(margins.top());

    // FIXME: Legacy animation?
    //init animation by 'm_rect'
    m_xAni->setStartValue(WindowMargin);
    m_xAni->setEndValue(0);

    m_widthAni->setStartValue(m_rect.width());
    m_widthAni->setEndValue(0);
}

void MainWindow::onFrontendWindowRectChanged(const QRect &rect)
{
    if (!window() || !window()->screen()) {
        return;
    }

    // Check if dock has moved to a different screen
    QScreen *currentScreen = window()->screen();
    QScreen *targetScreen = screenForDockCenter(rect);
    
    // If dock has moved to a different screen, update the window screen
    if (targetScreen != currentScreen) {
        window()->setScreen(targetScreen);
    }

    QRect dockGeometry = QRect(
        rect.x() / qApp->devicePixelRatio(),
        rect.y() / qApp->devicePixelRatio(),
        rect.width() / qApp->devicePixelRatio(),
        rect.height() / qApp->devicePixelRatio()
    );

    QRect screenGeometry = window()->screen()->geometry();
    QMargins newMargins(WindowMargin, WindowMargin, WindowMargin, WindowMargin);
    
    if (!m_isWayland && dockGeometry.width() > 0 && dockGeometry.height() > 0) {
        switch (m_daemonDockInter->position()) {
            case DOCK_TOP: {
                int visibleHeight = qMax(0, dockGeometry.y() + dockGeometry.height() - screenGeometry.top());
                newMargins.setTop(visibleHeight + WindowMargin);
                break;
            }
            case DOCK_BOTTOM: {
                int visibleHeight = qMax(0, screenGeometry.bottom() + 1 - dockGeometry.y());
                newMargins.setBottom(visibleHeight + WindowMargin);
                break;
            }
            case DOCK_LEFT: {
                break;
            }
            case DOCK_RIGHT: {
                int visibleWidth = qMax(0, screenGeometry.right() + 1 - dockGeometry.x());
                newMargins.setRight(visibleWidth + WindowMargin);
                break;
            }
        }
    }


    if (newMargins != m_currentMargins) {
        m_currentMargins = newMargins;
        
        auto layerShellWnd = ds::DLayerShellWindow::get(windowHandle());
        layerShellWnd->setLeftMargin(newMargins.left());
        layerShellWnd->setRightMargin(newMargins.right());
        layerShellWnd->setBottomMargin(newMargins.bottom());
        layerShellWnd->setTopMargin(newMargins.top());
    }

    m_xAni->setStartValue(WindowMargin);
    m_xAni->setEndValue(0);

    m_widthAni->setStartValue(m_rect.width());
    m_widthAni->setEndValue(0);
}

void MainWindow::showAni()
{
    if (m_trickTimer->isActive()) {
        return;
    }
    m_trickTimer->start();

    if (!m_hasComposite) {
        show();
        return;
    }

    move(m_rect.x(), m_rect.y());
    // setFixedWidth(0); // FIXME: Remove legacy animation. This line is commented out because it interferes with layershell anchoring

    show();
    m_aniGroup->setDirection(QAbstractAnimation::Backward);
    m_aniGroup->start();
}

void MainWindow::hideAni()
{
    if (m_trickTimer->isActive()) {
        return;
    }
    m_trickTimer->start();

    if (m_alwaysShow) {
        return;
    }
    if (!m_hasComposite) {
        hide();
        return;
    }
    m_aniGroup->setDirection(QAbstractAnimation::Forward);
    m_aniGroup->start();

    QTimer::singleShot(m_aniGroup->duration(), this, [ = ] {setVisible(false);});
}

void MainWindow::Show()
{
    if (m_aniGroup->state() == QAbstractAnimation::Running)
        return;

    if (!isVisible()) {
        showAni();
    }
}

void MainWindow::Hide()
{
    if (m_alwaysShow) {
        return;
    }
    if (m_aniGroup->state() == QAbstractAnimation::Running)
        return;

    if (isVisible()) {
        hideAni();
    }
}

void MainWindow::setX(int x)
{
    move(m_rect.x() + x, m_rect.y());
}

void MainWindow::CompositeChanged()
{
    // 屏蔽应用自己的动画，默认使用窗管窗口显示动画
    m_hasComposite = false;
}

void MainWindow::registerMonitor()
{
    if (m_regionMonitor) {
        delete m_regionMonitor;
        m_regionMonitor = nullptr;
    }
    m_regionMonitor = new DRegionMonitor(this);
    m_regionMonitor->registerRegion(QRegion(QRect()));
    connect(m_regionMonitor, &DRegionMonitor::buttonRelease, this, [ = ](const QPoint &p, const int flag) {
        Q_UNUSED(flag);
        if (!geometry().contains(p))
            if (!isHidden()) {
                hideAni();
            }
    });
}

void MainWindow::updatePrimaryScreen()
{
    if (!window())
        return;

    // Get the screen where dock is located instead of always using primary screen
    QRect dockRect = m_daemonDockInter->frontendWindowRect();
    QScreen *targetScreen = screenForDockCenter(dockRect);

    window()->setScreen(targetScreen);
    updateGeometry();
}

void MainWindow::initUI()
{
    setWindowFlags(Qt::FramelessWindowHint);
    setAttribute(Qt::WA_TranslucentBackground);

    QVBoxLayout *mainLayout = new QVBoxLayout();
    mainLayout->setContentsMargins(0, 0, 0, 10);
    mainLayout->setSpacing(0);

    QWidget *titleWidget = new QWidget;
    QHBoxLayout *titleLayout = new QHBoxLayout(titleWidget);
    titleLayout->setContentsMargins(20, 0, 10, 0);
    titleLayout->setAlignment(Qt::AlignVCenter);

    QLabel *titleLabel = new QLabel(tr("Clipboard"), this);
    DFontSizeManager::instance()->bind(titleLabel, DFontSizeManager::T3);

    m_clearButton = new IconButton(tr("Clear all"), this);
    connect(m_clearButton, &IconButton::clicked, m_model, &ClipboardModel::clear);

    titleLayout->addWidget(titleLabel);
    titleLayout->addStretch();
    titleLayout->addWidget(m_clearButton);
    m_clearButton->setFixedHeight(36);
    m_clearButton->setBackOpacity(200);
    m_clearButton->setRadius(8);
    m_clearButton->setFocusPolicy(Qt::StrongFocus);
    m_clearButton->setVisible(false);
    m_clearButton->installEventFilter(this);
    titleWidget->setFixedSize(WindowWidth, WindowTitleHeight);

    // Tips widget shows when data is copied, supports closing
    if (m_tipsWidget) {
        m_tipsWidget->setFixedSize(TipWidgetWidth, TipWidgetHeight);
        m_tipsWidget->setVisible(false);
        connect(m_tipsWidget, &TipsWidget::closeTips, [ = ] {
            m_showTipsWidget = false;
            // Create temporary config to save the value
            Dtk::Core::DConfig *config = Dtk::Core::DConfig::create("org.deepin.dde.clipboard", "org.deepin.dde.clipboard", QString(), nullptr);
            if (config && config->isValid()) {
                config->setValue(ShowTipsWidget, false);
                config->deleteLater();
            }
            // Immediately hide tips
            m_tipsWidget->setVisible(false);
        });
    }

    m_listview->setModel(m_model);
    m_listview->setItemDelegate(m_itemDelegate);
    m_listview->setFixedWidth(WindowWidth);//需固定，否则动画会变形
    DFontSizeManager::instance()->bind(m_listview, DFontSizeManager::T8);

    // 初始化占位符组件
    m_placeholderIcon->setFlat(true);
    m_placeholderIcon->setFocusPolicy(Qt::NoFocus);
    m_placeholderIcon->setAttribute(Qt::WA_TransparentForMouseEvents);
    m_placeholderIcon->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    m_placeholderIcon->setIconSize(QSize(128, 128));
    m_placeholderIcon->setIcon(DDciIcon::fromTheme("none"));

    m_placeholderLabel->setText(tr("Copy the content to clipboard"));
    m_placeholderLabel->setAlignment(Qt::AlignHCenter);
    DFontSizeManager::instance()->bind(m_placeholderLabel, DFontSizeManager::T8);

    QVBoxLayout *placeholderLayout = new QVBoxLayout(m_placeholderWidget);
    placeholderLayout->setAlignment(Qt::AlignCenter);
    placeholderLayout->setContentsMargins(0, 0, 0, 0);
    placeholderLayout->setSpacing(10);
    placeholderLayout->addWidget(m_placeholderIcon, 0, Qt::AlignHCenter);
    placeholderLayout->addWidget(m_placeholderLabel);

    bool hasInitialData = m_model->data().size() != 0;
    m_placeholderWidget->setVisible(!hasInitialData);
    m_listview->setVisible(hasInitialData);

    mainLayout->addWidget(titleWidget);
    if (m_tipsWidget) {
        mainLayout->addWidget(m_tipsWidget, 0, Qt::AlignHCenter);
        mainLayout->addSpacing(5);
    }
    mainLayout->addWidget(m_listview);
    mainLayout->addWidget(m_placeholderWidget);

    m_content->setLayout(mainLayout);

    QHBoxLayout *layout = new QHBoxLayout(this);
    layout->setSpacing(0);
    layout->setContentsMargins(0, 0, 0, 0);
    layout->addWidget(m_content);

    setMaskAlpha(static_cast<int>(this->opacity() * 255));
    setFocusPolicy(Qt::NoFocus);
    
    m_trickTimer->setInterval(300);
    m_trickTimer->setSingleShot(true);

    // 从应用主题获取圆角值并设置到窗口
    DPlatformTheme *theme = DGuiApplicationHelper::instance()->applicationTheme();
    m_cornerRadius = theme->windowRadius();
    m_windowHandle->setWindowRadius(m_cornerRadius);

    m_themeType= DGuiApplicationHelper::instance()->themeType();
    m_windowHandle->setBorderWidth(1);

    // LayerShell-implemented anchoring
    auto layerShellWnd = ds::DLayerShellWindow::get(windowHandle());

    layerShellWnd->setAnchors({ ds::DLayerShellWindow::AnchorRight,
                                ds::DLayerShellWindow::AnchorBottom,
                                ds::DLayerShellWindow::AnchorTop });
    layerShellWnd->setLayer(ds::DLayerShellWindow::LayerOverlay);
    // Let the compositor avoid dock exclusive zones on Wayland; X11 emulation already uses 0.
    layerShellWnd->setExclusiveZone(0);
    layerShellWnd->setKeyboardInteractivity(ds::DLayerShellWindow::KeyboardInteractivityOnDemand);
    // Initial size
    setFixedWidth(WindowWidth);

    updatePrimaryScreen();
}

void MainWindow::initAni()
{
    m_xAni->setEasingCurve(QEasingCurve::Linear);
    m_xAni->setPropertyName("x");
    m_xAni->setTargetObject(this);
    m_xAni->setDuration(AnimationTime / 2);

    m_widthAni->setEasingCurve(QEasingCurve::Linear);
    m_widthAni->setPropertyName("width");
    m_widthAni->setTargetObject(this);
    m_widthAni->setDuration(AnimationTime);

    m_aniGroup->addAnimation(m_xAni);
    m_aniGroup->addAnimation(m_widthAni);
}

void MainWindow::initConfig()
{
    // Create temporary config to read the value once
    Dtk::Core::DConfig *config = Dtk::Core::DConfig::create("org.deepin.dde.clipboard", "org.deepin.dde.clipboard", QString(), nullptr);
    
    if (!config || !config->isValid()) {
        if (config) {
            qWarning() << QString("DConfig is invalid, name:[%1], subpath:[%2]")
                .arg(config->name(), config->subpath());
            config->deleteLater();
        }
        return;
    }

    m_showTipsWidget = config->value(ShowTipsWidget, true).toBool();
    config->deleteLater();
    
    if (m_showTipsWidget) {
        m_tipsWidget = new TipsWidget(this);
    }
}

void MainWindow::updateTipsVisibility()
{
    if (!m_tipsWidget) {
        return;
    }

    bool hasData = m_model->data().size() != 0;
    m_tipsWidget->setVisible(hasData && m_showTipsWidget);
}

void MainWindow::initConnect()
{
    connect(qApp, &QGuiApplication::primaryScreenChanged, this, &MainWindow::updatePrimaryScreen, Qt::UniqueConnection);
    connect(DisplayManager::instance(), &DisplayManager::screenInfoChanged, this, &MainWindow::geometryChanged, Qt::QueuedConnection);
    connect(m_displayInter, &DBusDisplay::PrimaryRectChanged, this, &MainWindow::geometryChanged, Qt::QueuedConnection);

    connect(m_model, &ClipboardModel::dataChanged, this, [ = ] {
        bool hasData = m_model->data().size() != 0;
        m_clearButton->setVisible(hasData);
        m_listview->setVisible(hasData);
        m_placeholderWidget->setVisible(!hasData);
        
        updateTipsVisibility();
    });

    connect(m_itemDelegate, &ItemDelegate::hideWindow, this, [ = ] {
        hideAni();
    });

    connect(m_itemDelegate, &ItemDelegate::focusEscapeRequested, this, [this](bool forward) {
        QModelIndex currentIdx = m_listview->currentIndex();
        int rowCount = m_model->data().size();

        if (forward) {
            // Tab: 尝试跳到下一个 item，如果是最后一个则跳到清除按钮
            int nextRow = currentIdx.isValid() ? currentIdx.row() + 1 : 0;
            if (nextRow < rowCount) {
                setFocusToItem(nextRow);
            } else {
                m_clearButton->setFocus();
            }
        } else {
            // Backtab: 尝试跳到上一个 item 的关闭按钮，如果是第一个则跳到清除按钮
            int prevRow = currentIdx.isValid() ? currentIdx.row() - 1 : rowCount - 1;
            if (prevRow >= 0) {
                setFocusToItem(prevRow, true);
            } else {
                m_clearButton->setFocus();
            }
        }
    });

    connect(m_daemonDockInter, &DBusDaemonDock::FrontendWindowRectChanged, this, &MainWindow::onFrontendWindowRectChanged,  Qt::UniqueConnection);
    connect(m_daemonDockInter, &DBusDaemonDock::PositionChanged, this, &MainWindow::geometryChanged);

    connect(m_wmHelper, &DWindowManagerHelper::hasCompositeChanged, this, &MainWindow::CompositeChanged, Qt::QueuedConnection);

    connect(m_widthAni, &QVariantAnimation::valueChanged, this, [ = ](QVariant value) {
        int width = value.toInt();
        m_content->move(width - 300, m_content->pos().y());
    });

    QDBusServiceWatcher *m_watcher = new QDBusServiceWatcher(MONITOR_SERVICE, QDBusConnection::sessionBus());
    connect(m_watcher, &QDBusServiceWatcher::serviceRegistered, this, [ = ](const QString &service){
        if (MONITOR_SERVICE != service)
            return;
        registerMonitor();
    });

    connect(m_watcher, &QDBusServiceWatcher::serviceUnregistered, this, [ = ](const QString &service){
        if (MONITOR_SERVICE != service)
            return;
        disconnect(m_regionMonitor);
    });

    connect(this, &MainWindow::OpacityChanged, this, [this](double alpha) {
        setMaskAlpha(static_cast<int>(alpha * 255));
    });

    auto setOuterBorderColor = [this]() {
        auto outerBorderNewColor = outerBorderColor;
        if (m_themeType == DGuiApplicationHelper::ColorType::DarkType) {
            outerBorderNewColor.setAlpha(maskAlpha() + ALPHA_OFFSET * 2);
        }

        m_windowHandle->setBorderColor(outerBorderNewColor);
    };

    connect(this, &DBlurEffectWidget::maskAlphaChanged, [this, setOuterBorderColor]() {
        setOuterBorderColor();
        update();
    });

    connect(m_windowHandle, &DPlatformWindowHandle::windowRadiusChanged, this, [this](){
        if (m_cornerRadius == m_windowHandle->windowRadius())
            return;

        m_cornerRadius = m_windowHandle->windowRadius();
        update();
    });

    // 监听应用主题圆角变化
    DPlatformTheme *theme = DGuiApplicationHelper::instance()->applicationTheme();
    connect(theme, &DPlatformTheme::windowRadiusChanged, this, [this](int newRadius){
        if (m_cornerRadius == newRadius)
            return;
        m_cornerRadius = newRadius;
        m_windowHandle->setWindowRadius(m_cornerRadius);
        update();
    });

    connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, this, [this, setOuterBorderColor](DGuiApplicationHelper::ColorType type){
        if (!m_windowHandle || type == m_themeType)
            return;

        m_themeType = type;
        setOuterBorderColor();
        update();
    });

    setOuterBorderColor();
}

void MainWindow::adjustPosition()
{
    // 屏幕尺寸
    QRect rect = getDisplayScreen();
    rect.setWidth(WindowWidth);
    rect.setHeight(int(std::round(qreal(rect.height()))));

    QRect dockRect = m_daemonDockInter->frontendWindowRect();
    dockRect.setWidth(int(std::round(qreal(dockRect.width()))));
    dockRect.setHeight(int(std::round(qreal(dockRect.height()))));

    // 初始化剪切板位置
    switch (m_daemonDockInter->position()) {
    case DOCK_TOP:
        rect.moveTop(rect.top() + dockRect.height());
        rect.setHeight(rect.height() - dockRect.height());
        break;
    case DOCK_BOTTOM:
        rect.setHeight(rect.height() - dockRect.height());
        break;
    case DOCK_LEFT:
        rect.moveLeft(rect.left() + dockRect.width());
        break;
    default:;
    }

    // 左上下部分预留的间隙
    rect -= QMargins(0, WindowMargin, 0, WindowMargin);

    // 针对时尚模式的特殊处理
    // 只有任务栏显示的时候, 才额外偏移
    if(m_daemonDockInter->displayMode() == 0 && dockRect.width() * dockRect.height() > 0) {
        switch (m_daemonDockInter->position()) {
        case DOCK_TOP:
            rect -= QMargins(0, WindowMargin, 0, 0);
            break;
        case DOCK_BOTTOM:
            rect -= QMargins(0, 0, 0, WindowMargin);
            break;
        case DOCK_LEFT:
            rect -= QMargins(WindowMargin, 0, 0, 0);
            break;
        default:;
        }
    }

    setGeometry(rect);
    m_rect = rect;
    setFixedSize(rect.size());
    m_content->setFixedSize(rect.size());
}

QRect MainWindow::getDisplayScreen()
{
    QRect dockRect = m_daemonDockInter->frontendWindowRect();
    QScreen *targetScreen = screenForDockCenter(dockRect);
    
    return targetScreen->geometry();
}

void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
    //禁止窗口被拖动
    Q_UNUSED(event);
    return;
}

void MainWindow::paintEvent(QPaintEvent *e)
{
    DBlurEffectWidget::paintEvent(e);
    QPainter p(this);
    p.setRenderHint(QPainter::Antialiasing);
    QPen pen;
    pen.setWidth(1);

    auto innerBorderNewColor = innerBorderColor;
    if (m_themeType != DGuiApplicationHelper::DarkType) {
        innerBorderNewColor.setAlpha(maskAlpha()+ ALPHA_OFFSET);
    }

    pen.setColor(innerBorderNewColor);
    p.setPen(pen);
    p.drawRoundedRect(rect(), m_cornerRadius, m_cornerRadius);
}

void MainWindow::showEvent(QShowEvent *event)
{
    Q_EMIT clipboardVisibleChanged(true);
    DBlurEffectWidget::showEvent(event);

    static bool firstShow = true;
    if (firstShow) {
        firstShow = false;
        m_windowHandle->setEnableBlurWindow(false);
        m_windowHandle->setEnableBlurWindow(true);
    }

    activateWindow();
}

void MainWindow::hideEvent(QHideEvent *event)
{
    Q_EMIT clipboardVisibleChanged(false);
    DBlurEffectWidget::hideEvent(event);
}

QScreen *MainWindow::screenForDockCenter(const QRect &dockRectInDevicePixels) const
{
    if (dockRectInDevicePixels.isEmpty()) {
        return qApp->primaryScreen();
    }

    const qreal dpr = qApp->devicePixelRatio();
    
    // Convert dock center to logical coordinates
    QPoint dockCenterPoint = dockRectInDevicePixels.center() / dpr;
    
    // Find the screen containing the dock center point
    // Screen geometry is already in logical coordinates, no conversion needed
    for (auto s : qApp->screens()) {
        if (s->geometry().contains(dockCenterPoint)) {
            return s;
        }
    }
    
    // Fall back to primary screen if dock screen not found
    return qApp->primaryScreen();
}

bool MainWindow::event(QEvent *event)
{
    if (event->type() == QEvent::WindowDeactivate) {
        hideAni();
    }

    return DBlurEffectWidget::event(event);
}

void MainWindow::setFocusToItem(int row, bool focusCloseButton)
{
    QModelIndex idx = m_model->index(row, 0);
    if (!idx.isValid())
        return;

    m_listview->setCurrentIndex(idx);
    if (QWidget *w = m_listview->indexWidget(idx)) {
        w->setFocus();
        if (focusCloseButton) {
            if (ItemWidget *item = qobject_cast<ItemWidget *>(w))
                item->setCloseButtonFocusState(true);
        }
    }
}

bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{
    if (watched == m_clearButton && event->type() == QEvent::KeyPress) {
        QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
        if (keyEvent->key() == Qt::Key_Tab) {
            // 从清除按钮按 Tab，跳到第一个 item
            if (m_model->data().size() > 0) {
                setFocusToItem(0);
                return true;
            }
        } else if (keyEvent->key() == Qt::Key_Backtab) {
            // 从清除按钮按 Backtab，跳到最后一个 item 的关闭按钮
            int lastRow = m_model->data().size() - 1;
            if (lastRow >= 0) {
                setFocusToItem(lastRow, true);
                return true;
            }
        }
    }
    return DBlurEffectWidget::eventFilter(watched, event);
}

void MainWindow::resizeEvent(QResizeEvent *event)
{
    DBlurEffectWidget::resizeEvent(event);

    static bool firstResize = true;
    if (firstResize) {
        firstResize = false;
        m_windowHandle->setEnableBlurWindow(false);
        m_windowHandle->setEnableBlurWindow(true);
    }
}
