#include "framelessbase.h"

#include <QCoreApplication>
#include <QGuiApplication>
#include <QTimer>
#include <QVBoxLayout>
#include <QtCore/QDebug>
#include <QtCore/QFile>
#include <QtCore/QTime>
#include <QtCore/QTimer>
#include <QtGui/QPainter>
#include <QtGui/QWindow>
#include <QtWidgets/QApplication>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QStyle>
#include <QtWidgets/QMenuBar>
#include <QtCore/QPointer>
#include <QHBoxLayout>
#include <QIcon>
#include <QEventLoop>
#include <QCloseEvent>
#include "themesettingswidget.h"
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
#include <QtGui/QActionGroup>
#else
#include <QtWidgets/QActionGroup>
#endif

#include "widgetframe/windowbar.h"
#include "widgetframe/windowbutton.h"
#include "widgets/widgetwindowagent.h"

static inline void emulateLeaveEvent(QWidget *widget)
{
    Q_ASSERT(widget);
    if (!widget) {
        return;
    }
    QTimer::singleShot(0, widget, [widget]() {
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
        const QScreen *screen = widget->screen();
#else
        const QScreen *screen = widget->windowHandle()->screen();
#endif
        const QPoint globalPos = QCursor::pos(screen);
        if (!QRect(widget->mapToGlobal(QPoint{0, 0}), widget->size()).contains(globalPos)) {
            QCoreApplication::postEvent(widget, new QEvent(QEvent::Leave));
            if (widget->testAttribute(Qt::WA_Hover)) {
                const QPoint localPos = widget->mapFromGlobal(globalPos);
                const QPoint scenePos = widget->window()->mapFromGlobal(globalPos);
                static constexpr const auto oldPos = QPoint{};
                const Qt::KeyboardModifiers modifiers = QGuiApplication::keyboardModifiers();
#if (QT_VERSION >= QT_VERSION_CHECK(6, 4, 0))
                const auto event = new QHoverEvent(QEvent::HoverLeave,
                                                   scenePos,
                                                   globalPos,
                                                   oldPos,
                                                   modifiers);
                Q_UNUSED(localPos);
#elif (QT_VERSION >= QT_VERSION_CHECK(6, 3, 0))
                const auto event =  new QHoverEvent(QEvent::HoverLeave, localPos, globalPos, oldPos, modifiers);
                Q_UNUSED(scenePos);
#else
                const auto event =  new QHoverEvent(QEvent::HoverLeave, localPos, oldPos, modifiers);
                Q_UNUSED(scenePos);
#endif
                QCoreApplication::postEvent(widget, event);
            }
        }
    });
}

TMainWindow::TMainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    setAttribute(Qt::WA_DontCreateNativeAncestors);

    installWindowAgent();
}

bool TMainWindow::event(QEvent *event)
{
    switch (event->type()) {
    case QEvent::WindowActivate: {
        auto menu = menuWidget();
        if (menu) {
            menu->setProperty("bar-active", true);
            style()->polish(menu);
        }
        break;
    }

    case QEvent::WindowDeactivate: {
        auto menu = menuWidget();
        if (menu) {
            menu->setProperty("bar-active", false);
            style()->polish(menu);
        }
        break;
    }

    default:
        break;
    }
    return QMainWindow::event(event);
}

void TMainWindow::installWindowAgent()
{
    // 1. Setup window agent
    windowAgent = new QWK::WidgetWindowAgent(this);
    windowAgent->setup(this);

    auto titleLabel = new QLabel(windowTitle());
    titleLabel->setAlignment(Qt::AlignCenter);
    titleLabel->setObjectName(QStringLiteral("win-title-label"));

#ifndef Q_OS_MAC
    auto iconButton = new QWK::WindowButton();
    iconButton->setObjectName(QStringLiteral("icon-button"));
    iconButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);

    auto pinButton = new QWK::WindowButton();
    pinButton->setCheckable(true);
    pinButton->setObjectName(QStringLiteral("pin-button"));
    pinButton->setProperty("system-button", true);
    pinButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);

    auto minButton = new QWK::WindowButton();
    minButton->setObjectName(QStringLiteral("min-button"));
    minButton->setProperty("system-button", true);
    minButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);

    auto maxButton = new QWK::WindowButton();
    maxButton->setCheckable(true);
    maxButton->setObjectName(QStringLiteral("max-button"));
    maxButton->setProperty("system-button", true);
    maxButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);

    auto closeButton = new QWK::WindowButton();
    closeButton->setObjectName(QStringLiteral("close-button"));
    closeButton->setProperty("system-button", true);
    closeButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
#endif

    auto windowBar = new QWK::WindowBar();
#ifndef Q_OS_MAC
    windowBar->setIconButton(iconButton);
    windowBar->setPinButton(pinButton);
    windowBar->setMinButton(minButton);
    windowBar->setMaxButton(maxButton);
    windowBar->setCloseButton(closeButton);
#endif
    windowBar->setTitleLabel(titleLabel);
    windowBar->setHostWidget(this);

#ifndef Q_OS_MAC
    // 创建一个“设置”按钮，放在标题文本区域的最右侧，使其位于置顶按钮的左侧
    auto settingsButton = new QWK::WindowButton(windowBar);
    settingsButton->setObjectName(QStringLiteral("settings-button"));
    settingsButton->setProperty("system-button", true);
    settingsButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
    settingsButton->setIconNormal(QIcon(QStringLiteral(":/window-bar/more-line.svg")));
    QObject::connect(settingsButton, &QAbstractButton::clicked, this, [this]() {
        static QPointer<ThemeSettingsWidget> s_settings;
        if (!s_settings) {
            s_settings = new ThemeSettingsWidget();
            s_settings->setAttribute(Qt::WA_DeleteOnClose);
            s_settings->setWindowTitle(tr("设置"));
            s_settings->resize(520, 480);
        }
        s_settings->show();
        s_settings->raise();
        s_settings->activateWindow();
    });
    // 将按钮加入到 titleLabel 内部的水平布局（右对齐）
    {
        auto labelLayout = new QHBoxLayout(titleLabel);
        labelLayout->setContentsMargins(0, 0, 0, 0);
        labelLayout->addStretch();
        labelLayout->addWidget(settingsButton);
    }
#endif

    windowAgent->setTitleBar(windowBar);
#ifndef Q_OS_MAC
    windowAgent->setHitTestVisible(pinButton, true);
    windowAgent->setHitTestVisible(settingsButton, true);
    windowAgent->setSystemButton(QWK::WindowAgentBase::WindowIcon, iconButton);
    windowAgent->setSystemButton(QWK::WindowAgentBase::Minimize, minButton);
    windowAgent->setSystemButton(QWK::WindowAgentBase::Maximize, maxButton);
    windowAgent->setSystemButton(QWK::WindowAgentBase::Close, closeButton);
#endif

#ifdef Q_OS_MAC
    windowAgent->setSystemButtonAreaCallback([](const QSize &size) {
        static constexpr const int width = 75;
        return QRect(QPoint(size.width() - width, 0), QSize(width, size.height())); //
    });
#endif

    setMenuWidget(windowBar);

#ifndef Q_OS_MAC
    connect(this, &QMainWindow::windowTitleChanged, this, [titleLabel](const QString &title) {
        titleLabel->setText(title);
    });

    connect(windowBar, &QWK::WindowBar::pinRequested, this, [this, pinButton](bool pin) {
        if (isHidden() || isMinimized() || isMaximized() || isFullScreen()) {
            return;
        }
        setWindowFlag(Qt::WindowStaysOnTopHint, pin);
        show();
        pinButton->setChecked(pin);
    });
    connect(windowBar, &QWK::WindowBar::minimizeRequested, this, &QWidget::showMinimized);
    connect(windowBar, &QWK::WindowBar::maximizeRequested, this, [this, maxButton](bool max) {
        if (max) {
            showMaximized();
        } else {
            showNormal();
        }

        // It's a Qt issue that if a QAbstractButton::clicked triggers a window's maximization,
        // the button remains to be hovered until the mouse move. As a result, we need to
        // manually send leave events to the button.
        emulateLeaveEvent(maxButton);
    });
    connect(windowBar, &QWK::WindowBar::closeRequested, this, &QWidget::close);
#endif
}

TWidget::TWidget(QWidget *parent)
    : QWidget(parent)
    , m_menuWidget(nullptr)
    , m_mainLayout(nullptr)
{
    m_mainLayout = new QVBoxLayout(this);
    m_mainLayout->setContentsMargins(0, 0, 0, 0);
    m_mainLayout->setSpacing(0);
    setLayout(m_mainLayout);

    setAttribute(Qt::WA_DontCreateNativeAncestors);

    installWindowAgent();
}

QWidget *TWidget::menuWidget() const
{
    return m_menuWidget;
}

void TWidget::setMenuWidget(QWidget *widget)
{
    if (m_menuWidget) {
        m_mainLayout->removeWidget(m_menuWidget);
        delete m_menuWidget;
    }

    // 添加新标题栏到布局顶部
    m_menuWidget = widget;
    if (m_menuWidget) {
        m_mainLayout->insertWidget(0, m_menuWidget); // 插入到第一个位置
    }
}

bool TWidget::event(QEvent *event)
{
    switch (event->type()) {
    case QEvent::WindowActivate: {
        auto menu = menuWidget();
        if (menu) {
            menu->setProperty("bar-active", true);
            style()->polish(menu);
        }
        break;
    }

    case QEvent::WindowDeactivate: {
        auto menu = menuWidget();
        if (menu) {
            menu->setProperty("bar-active", false);
            style()->polish(menu);
        }
        break;
    }

    default:
        break;
    }
    return QWidget::event(event);
}

void TWidget::installWindowAgent()
{
    // 1. Setup window agent
    windowAgent = new QWK::WidgetWindowAgent(this);
    windowAgent->setup(this);

    auto titleLabel = new QLabel();
    titleLabel->setAlignment(Qt::AlignCenter);
    titleLabel->setObjectName(QStringLiteral("win-title-label"));

#ifndef Q_OS_MAC
    auto iconButton = new QWK::WindowButton();
    iconButton->setObjectName(QStringLiteral("icon-button"));
    iconButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);

    auto pinButton = new QWK::WindowButton();
    pinButton->setCheckable(true);
    pinButton->setObjectName(QStringLiteral("pin-button"));
    pinButton->setProperty("system-button", true);
    pinButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);

    auto minButton = new QWK::WindowButton();
    minButton->setObjectName(QStringLiteral("min-button"));
    minButton->setProperty("system-button", true);
    minButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);

    auto maxButton = new QWK::WindowButton();
    maxButton->setCheckable(true);
    maxButton->setObjectName(QStringLiteral("max-button"));
    maxButton->setProperty("system-button", true);
    maxButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);

    auto closeButton = new QWK::WindowButton();
    closeButton->setObjectName(QStringLiteral("close-button"));
    closeButton->setProperty("system-button", true);
    closeButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
#endif

    auto windowBar = new QWK::WindowBar();
#ifndef Q_OS_MAC
    windowBar->setIconButton(iconButton);
    windowBar->setPinButton(pinButton);
    windowBar->setMinButton(minButton);
    windowBar->setMaxButton(maxButton);
    windowBar->setCloseButton(closeButton);
#endif
    windowBar->setTitleLabel(titleLabel);
    windowBar->setHostWidget(this);

#ifndef Q_OS_MAC
    // 创建一个“设置”按钮，放在标题文本区域的最右侧，使其位于置顶按钮的左侧
    auto settingsButton = new QWK::WindowButton(windowBar);
    settingsButton->setObjectName(QStringLiteral("settings-button"));
    settingsButton->setProperty("system-button", true);
    settingsButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
    settingsButton->setIconNormal(QIcon(QStringLiteral(":/window-bar/more-line.svg")));
    QObject::connect(settingsButton, &QAbstractButton::clicked, this, [this]() {
        static QPointer<ThemeSettingsWidget> s_settings;
        if (!s_settings) {
            s_settings = new ThemeSettingsWidget();
            s_settings->setAttribute(Qt::WA_DeleteOnClose);
            s_settings->setWindowTitle(tr("设置"));
            s_settings->resize(520, 480);
        }
        s_settings->show();
        s_settings->raise();
        s_settings->activateWindow();
    });
    // 将按钮加入到 titleLabel 内部的水平布局（右对齐）
    {
        auto labelLayout = new QHBoxLayout(titleLabel);
        labelLayout->setContentsMargins(0, 0, 0, 0);
        labelLayout->addStretch();
        labelLayout->addWidget(settingsButton);
    }
#endif

    windowAgent->setTitleBar(windowBar);
#ifndef Q_OS_MAC
    windowAgent->setHitTestVisible(pinButton, true);
    windowAgent->setHitTestVisible(settingsButton, true);
    windowAgent->setSystemButton(QWK::WindowAgentBase::WindowIcon, iconButton);
    windowAgent->setSystemButton(QWK::WindowAgentBase::Minimize, minButton);
    windowAgent->setSystemButton(QWK::WindowAgentBase::Maximize, maxButton);
    windowAgent->setSystemButton(QWK::WindowAgentBase::Close, closeButton);
#endif

#ifdef Q_OS_MAC
    windowAgent->setSystemButtonAreaCallback([](const QSize &size) {
        static constexpr const int width = 75;
        return QRect(QPoint(size.width() - width, 0), QSize(width, size.height())); //
    });
#endif

    setMenuWidget(windowBar);

#ifndef Q_OS_MAC
    connect(windowBar, &QWK::WindowBar::pinRequested, this, [this, pinButton](bool pin) {
        if (isHidden() || isMinimized() || isMaximized() || isFullScreen()) {
            return;
        }
        setWindowFlag(Qt::WindowStaysOnTopHint, pin);
        show();
        pinButton->setChecked(pin);
    });
    connect(windowBar, &QWK::WindowBar::minimizeRequested, this, &QWidget::showMinimized);
    connect(windowBar, &QWK::WindowBar::maximizeRequested, this, [this, maxButton](bool max) {
        if (max) {
            showMaximized();
        } else {
            showNormal();
        }

        // It's a Qt issue that if a QAbstractButton::clicked triggers a window's maximization,
        // the button remains to be hovered until the mouse move. As a result, we need to
        // manually send leave events to the button.
        emulateLeaveEvent(maxButton);
    });
    connect(windowBar, &QWK::WindowBar::closeRequested, this, &QWidget::close);
#endif
}

// ---------------- TDialog (QDialog-based) ----------------
TDialog::TDialog(QWidget *parent)
    : QDialog(parent)
    , m_menuWidget(nullptr)
    , m_mainLayout(nullptr)
{
    // QDialog 默认是 Qt::Dialog 窗口类型
    setAttribute(Qt::WA_DontCreateNativeAncestors);

    m_mainLayout = new QVBoxLayout(this);
    m_mainLayout->setContentsMargins(0, 0, 0, 0);
    m_mainLayout->setSpacing(0);
    setLayout(m_mainLayout);

    // 启用与 TWidget 一致的自定义无边框标题栏/按钮
    installWindowAgent();
}

QWidget *TDialog::menuWidget() const
{
    return m_menuWidget;
}

void TDialog::setMenuWidget(QWidget *widget)
{
    if (m_menuWidget) {
        m_mainLayout->removeWidget(m_menuWidget);
        delete m_menuWidget;
    }

    m_menuWidget = widget;
    if (m_menuWidget) {
        m_mainLayout->insertWidget(0, m_menuWidget);
    }
}

bool TDialog::event(QEvent *event)
{
    switch (event->type()) {
    case QEvent::WindowActivate: {
        auto menu = menuWidget();
        if (menu) {
            menu->setProperty("bar-active", true);
            style()->polish(menu);
        }
        break;
    }
    case QEvent::WindowDeactivate: {
        auto menu = menuWidget();
        if (menu) {
            menu->setProperty("bar-active", false);
            style()->polish(menu);
        }
        break;
    }
    default:
        break;
    }
    return QDialog::event(event);
}

void TDialog::installWindowAgent()
{
    // 1. Setup window agent
    windowAgent = new QWK::WidgetWindowAgent(this);
    windowAgent->setup(this);

    auto titleLabel = new QLabel(windowTitle());
    titleLabel->setAlignment(Qt::AlignCenter);
    titleLabel->setObjectName(QStringLiteral("win-title-label"));

#ifndef Q_OS_MAC
    auto iconButton = new QWK::WindowButton();
    iconButton->setObjectName(QStringLiteral("icon-button"));
    iconButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);

    auto pinButton = new QWK::WindowButton();
    pinButton->setCheckable(true);
    pinButton->setObjectName(QStringLiteral("pin-button"));
    pinButton->setProperty("system-button", true);
    pinButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);

    auto minButton = new QWK::WindowButton();
    minButton->setObjectName(QStringLiteral("min-button"));
    minButton->setProperty("system-button", true);
    minButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);

    auto maxButton = new QWK::WindowButton();
    maxButton->setCheckable(true);
    maxButton->setObjectName(QStringLiteral("max-button"));
    maxButton->setProperty("system-button", true);
    maxButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);

    auto closeButton = new QWK::WindowButton();
    closeButton->setObjectName(QStringLiteral("close-button"));
    closeButton->setProperty("system-button", true);
    closeButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
#endif

    auto windowBar = new QWK::WindowBar();
#ifndef Q_OS_MAC
    windowBar->setIconButton(iconButton);
    windowBar->setPinButton(pinButton);
    windowBar->setMinButton(minButton);
    windowBar->setMaxButton(maxButton);
    windowBar->setCloseButton(closeButton);
#endif
    windowBar->setTitleLabel(titleLabel);
    windowBar->setHostWidget(this);

#ifndef Q_OS_MAC
    // 创建一个“设置”按钮，放在标题文本区域的最右侧，使其位于置顶按钮的左侧
    auto settingsButton = new QWK::WindowButton(windowBar);
    settingsButton->setObjectName(QStringLiteral("settings-button"));
    settingsButton->setProperty("system-button", true);
    settingsButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
    settingsButton->setIconNormal(QIcon(QStringLiteral(":/window-bar/more-line.svg")));
    QObject::connect(settingsButton, &QAbstractButton::clicked, this, [this]() {
        static QPointer<ThemeSettingsWidget> s_settings;
        if (!s_settings) {
            s_settings = new ThemeSettingsWidget();
            s_settings->setAttribute(Qt::WA_DeleteOnClose);
            s_settings->setWindowTitle(tr("设置"));
            s_settings->resize(520, 480);
        }
        s_settings->show();
        s_settings->raise();
        s_settings->activateWindow();
    });
    // 将按钮加入到 titleLabel 内部的水平布局（右对齐）
    {
        auto labelLayout = new QHBoxLayout(titleLabel);
        labelLayout->setContentsMargins(0, 0, 0, 0);
        labelLayout->addStretch();
        labelLayout->addWidget(settingsButton);
    }
#endif

    windowAgent->setTitleBar(windowBar);
#ifndef Q_OS_MAC
    windowAgent->setHitTestVisible(pinButton, true);
    windowAgent->setHitTestVisible(settingsButton, true);
    windowAgent->setSystemButton(QWK::WindowAgentBase::WindowIcon, iconButton);
    windowAgent->setSystemButton(QWK::WindowAgentBase::Minimize, minButton);
    windowAgent->setSystemButton(QWK::WindowAgentBase::Maximize, maxButton);
    windowAgent->setSystemButton(QWK::WindowAgentBase::Close, closeButton);
#endif

#ifdef Q_OS_MAC
    windowAgent->setSystemButtonAreaCallback([](const QSize &size) {
        static constexpr const int width = 75;
        return QRect(QPoint(size.width() - width, 0), QSize(width, size.height())); //
    });
#endif

    setMenuWidget(windowBar);

#ifndef Q_OS_MAC
    connect(this, &QDialog::windowTitleChanged, this, [titleLabel](const QString &title) {
        titleLabel->setText(title);
    });

    connect(windowBar, &QWK::WindowBar::pinRequested, this, [this, pinButton](bool pin) {
        if (isHidden() || isMinimized() || isMaximized() || isFullScreen()) {
            return;
        }
        setWindowFlag(Qt::WindowStaysOnTopHint, pin);
        show();
        pinButton->setChecked(pin);
    });
    connect(windowBar, &QWK::WindowBar::minimizeRequested, this, &QWidget::showMinimized);
    connect(windowBar, &QWK::WindowBar::maximizeRequested, this, [this, maxButton](bool max) {
        if (max) {
            showMaximized();
        } else {
            showNormal();
        }
        emulateLeaveEvent(maxButton);
    });
    connect(windowBar, &QWK::WindowBar::closeRequested, this, &QWidget::close);
#endif
}

void TDialog::accept()
{
    QDialog::accept();
}

void TDialog::reject()
{
    QDialog::reject();
}
