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

#include "content.h"

#include <DApplication>
#include <DSuggestButton>
#include <DFontSizeManager>
#include <DGuiApplicationHelper>
#include <DStyle>
#include <DPushButton>

#include <QScrollArea>
#include <QPushButton>
#include <QCheckBox>
#include <QHBoxLayout>
#include <QLabel>
#include <QApplication>
#include <QDebug>
#include <QFontMetrics>
#include <QScroller>
#include <QStyleOptionButton>
#include <QStylePainter>
#include <QtConcurrent>
#include <QThread>
#include <QTranslator>
#include <QTextDocument>

#include <unistd.h>

DWIDGET_USE_NAMESPACE

namespace {

// TODO Change to DSuggestButton of v25 chameleton style.
class LicenseDialogButton : public DPushButton
{
public:
    explicit LicenseDialogButton(bool highlighted, QWidget *parent = nullptr)
        : DPushButton(parent)
        , m_highlighted(highlighted)
    {
        DStyle::setFrameRadius(this, 6);
        setFlat(true);
    }

protected:
    void initStyleOption(QStyleOptionButton *option) const override
    {
        DPushButton::initStyleOption(option);

        qreal backgroundOpacity = 0.15;
        if (option->state.testFlag(QStyle::State_Enabled)) {
            if (option->state.testFlag(QStyle::State_Sunken)) {
                backgroundOpacity = 0.25;
            } else if (option->state.testFlag(QStyle::State_MouseOver)) {
                backgroundOpacity = 0.2;
            }
        }

        QColor backgroundColor(Qt::black);
        backgroundColor.setAlphaF(backgroundOpacity);
        option->palette.setColor(QPalette::Button, backgroundColor);

        if (m_highlighted) {
            QColor textColor = option->palette.highlight().color();
            option->palette.setColor(QPalette::ButtonText, textColor);
        }

        option->state.setFlag(QStyle::State_MouseOver, false);
        option->state.setFlag(QStyle::State_Sunken, false);
        option->state.setFlag(QStyle::State_On, false);
    }

    void paintEvent(QPaintEvent *) override
    {
        QStyleOptionButton option;
        initStyleOption(&option);

        QStylePainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing);
        painter.setPen(Qt::NoPen);
        painter.setBrush(option.palette.button());
        const int radius = DStyle::pixelMetric(style(), DStyle::PM_FrameRadius, &option, this);
        painter.drawRoundedRect(option.rect, radius, radius);
        painter.drawControl(QStyle::CE_PushButton, option);
    }

private:
    bool m_highlighted = false;
};

}

Content::Content(QWidget *parent)
    : QWidget(parent)
    , m_scrollArea(new QScrollArea)
    , m_acceptCheck(new QCheckBox)
    , m_cancelBtn(new LicenseDialogButton(false))
    , m_acceptBtn(new LicenseDialogButton(true))
    , m_source(new QLabel)
    , m_languageBtn(new DButtonBox)
    , m_isCn(false)
    , m_hasCn(false)
    , m_hasEn(false)
{
    m_scrollArea->setAccessibleName("ScrollArea");
    m_acceptCheck->setAccessibleName("AcceptCheck");
    m_cancelBtn->setAccessibleName("CancelBtn");
    m_acceptBtn->setAccessibleName("AcceptBtn");
    m_source->setAccessibleName("SourceLabel");
    m_languageBtn->setAccessibleName("LanguageBtn");
    QVBoxLayout *layout = new QVBoxLayout;
    layout->setContentsMargins(0, 0, 0, 0);
    layout->setSpacing(0);

    setLayout(layout);

    DButtonBoxButton *btnChinese = new DButtonBoxButton("中文");
    btnChinese->setAccessibleName("ChineseBtn");
    btnChinese->setFixedSize(90, 36);
    DButtonBoxButton *btnEnginsh = new DButtonBoxButton("English");
    btnEnginsh->setAccessibleName("EnglishBtn");
    btnEnginsh->setFixedSize(90, 36);
    QList<DButtonBoxButton *> btnlist;
    btnlist.append(btnChinese);
    btnlist.append(btnEnginsh);
    m_languageBtn->setButtonList(btnlist, true);

    m_languageBtn->setId(btnChinese, 1);
    m_languageBtn->setId(btnEnginsh, 0);

    layout->addWidget(m_languageBtn, 0, Qt::AlignHCenter);

    m_scrollArea->setMinimumSize(390, 300);
    m_scrollArea->setWidgetResizable(true);
    m_scrollArea->setFrameStyle(QFrame::NoFrame);
    m_scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    m_scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
    m_scrollArea->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding);
    m_scrollArea->setContentsMargins(0, 0, 0, 0);
    m_scrollArea->setStyleSheet("QScrollArea { background: transparent; }"
                                "QScrollArea > QWidget > QWidget { background: transparent; }");
    QScroller::grabGesture(m_scrollArea->viewport(), QScroller::LeftMouseButtonGesture);

    QWidget *sourceWidget = new QWidget(this);
    sourceWidget->setAccessibleName("SourceWidget");
    QVBoxLayout *sourceLayout = new QVBoxLayout;
    sourceWidget->setLayout(sourceLayout);
    sourceLayout->addWidget(m_source);

    m_cancelBtn->setFixedHeight(36);
    m_acceptBtn->setFixedHeight(36);
    m_source->setTextFormat(Qt::MarkdownText);
    m_source->setWordWrap(true);
    m_source->setOpenExternalLinks(true);
    // 左右边距20
    m_source->setContentsMargins(20, 0, 20, 0);

    m_scrollArea->setWidget(sourceWidget);

    QVBoxLayout *bottomLayout = new QVBoxLayout;
    bottomLayout->setContentsMargins(0, 0, 0, 6);
    bottomLayout->setSpacing(10);
    bottomLayout->addWidget(m_acceptCheck, 0, Qt::AlignHCenter);

    QHBoxLayout *buttonRow = new QHBoxLayout;
    buttonRow->setContentsMargins(6, 0, 6, 0);
    buttonRow->setSpacing(6);

    m_cancelBtn->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
    m_acceptBtn->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);

    buttonRow->addWidget(m_cancelBtn, 1);
    buttonRow->addWidget(m_acceptBtn, 1);

    bottomLayout->addLayout(buttonRow);

    m_bottom = new QWidget(this);
    m_bottom->setLayout(bottomLayout);
    m_bottom->setAccessibleName("ContentBottomWidget");

    layout->addWidget(m_scrollArea);
    layout->addSpacing(20);
    layout->addWidget(m_bottom);

    m_acceptBtn->setDisabled(true);

    // 当父进程退出后，此对话框自动退出
    __pid_t idp;
    idp = getppid();

    static bool quit = false;
    QFuture<void> future = QtConcurrent::run([ = ] () {
        while(!quit) {
            if (!QFile(QString("/proc/%1/exe").arg(idp)).exists()) {
                qApp->quit();
                break;
            }

            QThread::msleep(100);
        }
    });

    connect(qApp, &QApplication::aboutToQuit, this, [ = ] {
        quit = true;
    });

    connect(m_cancelBtn, &QPushButton::clicked, this, [ = ] {
        qApp->exit(-1);
    });

    connect(m_acceptBtn, &QPushButton::clicked, this, [ = ] {
        qApp->exit(96);
    });

    connect(m_acceptCheck, &QCheckBox::toggled, m_acceptBtn, &QPushButton::setEnabled);

    connect(m_languageBtn, &DButtonBox::buttonClicked, [this](QAbstractButton * value) {
        m_isCn = m_languageBtn->id(value);
        updateContent();
    });

    m_isCn = QLocale::system().language() == QLocale::Chinese;
    updateContent();
    updateLanguageBtn();

    DFontSizeManager::instance()->bind(m_acceptCheck, DFontSizeManager::SizeType::T8, 70);
}

void Content::setHideBottom(const bool &status)
{
    m_bottom->setVisible(!status);
}

int Content::calWidgetWidth()
{
    const int cancelMin = qMax(m_cancelBtn->minimumSizeHint().width(), m_cancelBtn->minimumWidth());
    const int acceptMin = qMax(m_acceptBtn->minimumSizeHint().width(), m_acceptBtn->minimumWidth());
    const int width = 6 + cancelMin + 6 + acceptMin + 6;
    return width;
}

void Content::setSource(const QString &source)
{
    if (source.isEmpty() || !QFile::exists(source))
        return;

    QFile file(source);
    if (!file.open(QIODevice::Text | QIODevice::ReadOnly)) {
        qWarning() << "Set source error: " << file.errorString();
        return;
    }

    QTextDocument doc;
    doc.setMarkdown(file.readAll());
    file.close();

    m_source->setText(doc.toHtml());
    updateWindowHeight();
}

void Content::setAllowCheckBoxText(const QString &text)
{
    m_allow = text;
}

void Content::setEnAllowCheckBoxText(const QString &text)
{
    m_enallow = text;
}

void Content::setCnSource(const QString &source)
{
    m_cn = source;
    setSource(source);
    updateLanguageBtn();
    m_languageBtn->button(1)->setChecked(true);
}

void Content::setEnSource(const QString &source)
{
    m_en = source;
    setSource(source);
    updateLanguageBtn();
    m_languageBtn->button(0)->setChecked(true);
}

// 中英文都存在,选中本地语言
void Content::updateLocaleSource()
{
    if (!m_hasCn && !m_hasEn)
        return;
    if (QLocale::system().language() == QLocale::Chinese) {
        m_isCn = true;
        m_languageBtn->button(1)->setChecked(true);
    } else {
        m_isCn = false;
        m_languageBtn->button(0)->setChecked(true);
    }

    updateContent();
}

void Content::updateLanguageBtn()
{
    m_hasCn = QFile::exists(m_cn);
    m_hasEn = QFile::exists(m_en);
    m_languageBtn->setVisible(m_hasCn && m_hasEn);
}

void Content::updateContent()
{
    if (!m_translator) {
        m_translator = new QTranslator(this);
    } else {
        qApp->removeTranslator(m_translator);
    }

    setSource(m_isCn ? m_cn : m_en);
    m_acceptCheck->setText(m_isCn ? m_allow : m_enallow);
    m_acceptCheck->setVisible(m_isCn ? !m_allow.isEmpty() : !m_enallow.isEmpty());
    QString tsFilePath;
    if (m_hasCn && m_hasEn) {
        tsFilePath = QString("/usr/share/dde-session-ui/translations/dde-session-ui_%1").arg(m_isCn ? "zh_CN" : "en_US");
    } else {
        tsFilePath = QString("/usr/share/dde-session-ui/translations/dde-session-ui_%1").arg(QLocale::system().name());
    }

    if (m_translator->load(tsFilePath)) {
        qApp->installTranslator(m_translator);
    }

    m_cancelBtn->setText(tr("Cancel", "button"));
    m_acceptBtn->setText(tr("Confirm", "button"));
    m_acceptBtn->setEnabled(m_allow.isEmpty() || (!m_allow.isEmpty() && m_acceptCheck->isChecked()));

    Q_EMIT sourceChanged(m_isCn);
}

// 根据文本多少，调整窗口大小
void Content::updateWindowHeight()
{
    QTextDocument doc;
    doc.setHtml(m_source->text());
    doc.setTextWidth(m_scrollArea->width() - 40);
    
    int contentHeight = static_cast<int>(doc.size().height());
    int minHeight = qBound(100, contentHeight, 491);
    m_scrollArea->setMinimumHeight(minHeight);
}
