/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 *
 * Copyright (C) 2024 KylinSoft  Co., Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 */
#include <QAction>
#include <QMenu>
#include <QPainter>
#include <QMessageBox>
#include <QApplication>
#include <QDebug>
#include <QGSettings>
#include <QStandardPaths>
#include "fontunit.h"
#include "ukcccommon.h"
using namespace ukcc;

#define STYLE_FONT_SCHEMA  "org.ukui.style"
#define SYSTEM_FONT_EKY "system-font-size"
#define APPLY_FONT_KEY "system-font"

#define UKCC_FONT_SCHEMA  "org.ukui.control-center"
#define FONT_STYLE_KEY "fontStyle"

#define KYLIN_GTK_GSTTINGS "org.mate.interface"

FontUnit::FontUnit(const ViewData* viewData, QString installPath, QWidget *parent)
{
    m_applyFont = false;
    m_installPath = installPath;
    m_viewData = new ViewData();
    m_viewData->family = viewData->family;
    m_viewData->name = viewData->name;
    m_viewData->path = viewData->path;
    m_viewData->style = viewData->style;

    m_fontInterface = new QDBusInterface("org.ukui.ukcc.session",
                                         "/Font",
                                         "org.ukui.ukcc.session.Font",
                                         QDBusConnection::sessionBus(), this);
    if (!m_fontInterface->isValid()) {
        qCritical() << "org.ukui.ukcc.session.Font DBus error:" << m_fontInterface->lastError();
    }

    const QByteArray styleID(STYLE_FONT_SCHEMA);
    m_styleSettings = new QGSettings(styleID, QByteArray(), this);
    if (!m_styleSettings) {
        qCritical() << "org.ukui.style init failed";
    }

    const QByteArray ukccID(UKCC_FONT_SCHEMA);
    m_ukccSettings = new QGSettings(ukccID, QByteArray(), this);
    if (!m_ukccSettings) {
        qCritical() << "org.ukui.control-center init failed";
    }

    const QByteArray gtkID(KYLIN_GTK_GSTTINGS);
    m_gtkSettings = new QGSettings(gtkID, QByteArray(), this);
    if (!m_gtkSettings) {
        qCritical() << "org.mate.interface init failed";
    }

    setWidgetUi();
    setWidgetLayout();
    setupConnect();
    setWidgetContent();
}

FontUnit::~FontUnit()
{
    m_applyFont = false;
    m_installPath.clear();
    if (m_viewData) {
        delete m_viewData;
        m_viewData = nullptr;
    }
}

bool FontUnit::isUsingFont()
{
    QString fontName = m_styleSettings->get(APPLY_FONT_KEY).toString();
    QString fontStyle = m_ukccSettings->get(FONT_STYLE_KEY).toString();
    if (m_viewData->family == "C059" || m_viewData->family == "Z003") {
        return (fontName.contains(m_viewData->family)) && (fontStyle == m_viewData->style);
    } else {
        return (fontName == m_viewData->family) && (fontStyle == m_viewData->style);
    }
}

void FontUnit::setWidgetUi()
{
    setContentsMargins(8, 8, 0, 8);
    setFixedSize(197, 156);
    setWindowFlag(Qt::Tool);
    setWindowModality(Qt::WindowModal);
    setWindowModality(Qt::ApplicationModal);
    setAutoFillBackground(true);
    setBackgroundRole(QPalette::Base);
    setAttribute(Qt::WA_DeleteOnClose, true);
    if (UkccCommon::isV11()) {
        m_fontPreviewLabel = new QLabel(tr("Build a Chinese brand of world operating systems"), this);
    } else {
        m_fontPreviewLabel = new QLabel(tr("Open source collaboration, creating a better future together"), this);
    }
    m_fontPreviewLabel->setWordWrap(true);
    m_fontPreviewLabel->setAlignment(Qt::AlignTop|Qt::AlignLeft);
    m_fontPreviewLabel->setFixedSize(176, 68);

    m_fontNameLabel = new KLabel(this);
    m_fontNameLabel->setText(m_viewData->name);
    m_fontNameLabel->setWordWrap(false);
    m_fontNameLabel->setFixedHeight(21);
    m_fontNameLabel->setAlignment(Qt::AlignVCenter|Qt::AlignLeft);

    m_fontStyleLabel = new LightLabel(tr("1 font style"), this);
    m_fontStyleLabel->setWordWrap(true);
    m_fontStyleLabel->setAlignment(Qt::AlignBottom|Qt::AlignLeft);
    m_fontStyleLabel->setFixedHeight(26);

    m_fontToolButton = new QToolButton(this);
    m_fontToolButton->setAutoRaise(true);
    m_fontToolButton->setPopupMode(QToolButton::InstantPopup);

    m_applyFontAction = new QAction(tr("Apply Font"), m_fontToolButton);
    m_removeFontAction = new QAction(tr("Remove Font"), m_fontToolButton);
    m_checkFontAction = new QAction(tr("Check Font"), m_fontToolButton);

    m_fontMenu = new QMenu(m_fontToolButton);
    m_fontMenu->addAction(m_applyFontAction);
    m_fontMenu->addAction(m_checkFontAction);
    m_fontMenu->addAction(m_removeFontAction);

    m_fontToolButton->setMenu(m_fontMenu);
    m_fontToolButton->setIcon(QIcon::fromTheme("view-more-horizontal-symbolic"));
    m_fontToolButton->setProperty("useButtonPalette", true);
    m_fontToolButton->setFixedSize(36, 36);
}

void FontUnit::setWidgetLayout()
{
    m_leftVerLayout = new QVBoxLayout();
    m_leftVerLayout->addStretch();
    m_leftVerLayout->addWidget(m_fontNameLabel);
    m_leftVerLayout->addStretch();
    m_leftVerLayout->addWidget(m_fontStyleLabel);

    m_bottomHorLayout = new QHBoxLayout();
    m_bottomHorLayout->setSpacing(8);
    m_bottomHorLayout->addLayout(m_leftVerLayout);
    m_bottomHorLayout->addWidget(m_fontToolButton);

    m_baseVerLayout = new QVBoxLayout(this);
    m_baseVerLayout->addWidget(m_fontPreviewLabel);
    m_baseVerLayout->addStretch();
    m_baseVerLayout->addLayout(m_bottomHorLayout);
}

void FontUnit::setWidgetContent()
{
    m_applyFont = isUsingFont();
    if (!m_viewData->path.contains(m_installPath)) {
        m_removeFontAction->setEnabled(false);
    }

    if (m_applyFont) {
        m_applyFontAction->setEnabled(false);
        m_removeFontAction->setEnabled(false);
    } else {
        if (m_viewData->path.contains(m_installPath)) {
            m_removeFontAction->setEnabled(true);
        }
        m_applyFontAction->setEnabled(true);
    }

    // fontPreview
    QFont textFont = QFont();
    textFont.setFamily(m_viewData->name);
    textFont.setPixelSize(20);
    QStringList style = m_viewData->style.split(' ');
    for (int i = 0; i < style.size(); i++) {
        if (style.at(i) == "Bold") {
            textFont.setBold(true);
        } else if (style.at(i) == "Italic") {
            textFont.setItalic(true);
        } else if (style.at(i) == "Oblique") {
            textFont.setStyle(QFont::StyleOblique);
        }
    }
    m_fontPreviewLabel->setFont(textFont);
    QFontMetrics fontMetrics(m_fontPreviewLabel->font());
    QString previewText = m_fontPreviewLabel->text();
    int fontWidth = fontMetrics.horizontalAdvance(previewText);

    static const int PREVIEW_WIDTH = 170;
    static const int PREVIEW_HEIGHT = 63;
    static const int SPACING = 32;
    int fontLine = fontWidth / PREVIEW_WIDTH;
    if (fontWidth % PREVIEW_WIDTH != 0) {
        fontLine = fontLine + 1;
    }
    int fontHeight = fontMetrics.height();
    QString language = QLocale::system().name();
    if (language != "zh_CN") {
        if (fontLine >= 2 && (2 * fontHeight > PREVIEW_HEIGHT)) {
            m_fontPreviewLabel->setText(fontMetrics.elidedText(previewText, Qt::ElideRight, PREVIEW_WIDTH));
            m_fontPreviewLabel->setToolTip(previewText);
        }

        if (fontLine >= 3 && (3 * fontHeight > PREVIEW_HEIGHT)) {
            m_fontPreviewLabel->setText(fontMetrics.elidedText(previewText, Qt::ElideRight, (PREVIEW_WIDTH * 2 - SPACING)));
            m_fontPreviewLabel->setToolTip(previewText);
        }

        if (fontLine >= 4) {
            m_fontPreviewLabel->setText(fontMetrics.elidedText(previewText, Qt::ElideRight, (PREVIEW_WIDTH * 3)));
            m_fontPreviewLabel->setToolTip(previewText);
        }
    }

    // fontName
    QFont nameFont = QFont();
    nameFont.setFamily("Noto Sans CJK SC");
    nameFont.setWeight(QFont::Weight::Normal);
    nameFont.setPointSize(10);
    m_fontNameLabel->setFont(nameFont);

    // fontStyle
    QFont styleFont = QFont();
    styleFont.setFamily("Noto Sans CJK SC");
    styleFont.setWeight(QFont::Weight::Normal);
    styleFont.setPixelSize(12);
    m_fontStyleLabel->setFont(styleFont);
}

void FontUnit::setupConnect()
{
    connect(m_styleSettings , &QGSettings::changed, this, [=](const QString &key) {
        styleSettingChangeSlot();
    });

    connect(m_ukccSettings , &QGSettings::changed, this, [=](const QString &key) {
        styleSettingChangeSlot();
    });

    connect(m_gtkSettings , &QGSettings::changed, this, [=](const QString &key) {
        styleSettingChangeSlot();
    });

    connect(m_applyFontAction, &QAction::triggered, this, &FontUnit::applyFontSlot);
    connect(m_removeFontAction, &QAction::triggered, this, &FontUnit::removeFontSlot);
    connect(m_checkFontAction, &QAction::triggered, this, &FontUnit::checkFontSlot);
}

void FontUnit::styleSettingChangeSlot()
{
    setWidgetContent();
    this->update();
}

void FontUnit::applyFontSlot()
{
    qDebug() << Q_FUNC_INFO << "apply font" << m_viewData->family << m_viewData->path;
    m_fontInterface->call("applyFont", m_viewData->family, m_viewData->path, m_viewData->style);
    m_applyFont = true;
    this->update();
}

void FontUnit::removeFontSlot()
{
    QMessageBox msg;
    msg.setIcon(QMessageBox::Warning);
    msg.addButton(tr("Cancle"), QMessageBox::RejectRole);
    msg.addButton(tr("Uninstall"), QMessageBox::AcceptRole);
    msg.setText(tr("Are you sure to uninstall this font"));
    msg.setInformativeText(tr("If uninstall this font, some fonts may not display as expected."));
    int ret = msg.exec();
    if (ret) {
        m_fontInterface->call("uninstallFont", m_viewData->path, m_viewData->name);
        emit remoteFontSig(m_viewData->path, m_viewData->name);
        qDebug() << Q_FUNC_INFO << m_viewData->path << "need uninstall";
        this->close();
        this->deleteLater();
    } else {
        qDebug() << Q_FUNC_INFO << "uninstall font cancel";
    }
}

void FontUnit::checkFontSlot()
{
    m_popupFontInfo = new PopupFontInfo(m_viewData->path, this);
    if (m_popupFontInfo) {
        m_popupFontInfo->show();
    }
}

void FontUnit::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);

    // 应用字体边框颜色
    QPen pen(Qt::transparent);
    if (m_applyFont) {
        QPalette pal;
        pen.setColor(pal.highlight().color());
    }
    pen.setWidth(5);
    painter.setPen(pen);

    // 设置填充的画刷（可选）
    QColor color = QColor("#F6F6F6");
    QColor installColor = QColor("#E6E6E6");
    QString currentThemeMode = m_styleSettings->get("style-name").toString();
    if ("ukui-dark" == currentThemeMode || "ukui-black" == currentThemeMode){
        if (m_isMouseOpt || m_installFlag) {
            QPalette pal;
            painter.setBrush(pal.window());
        }
    } else if (m_isMouseOpt || m_installFlag) {
        QBrush brush(installColor);
        painter.setBrush(brush);
    } else {
        QBrush brush(color);
        painter.setBrush(brush);
    }

    // 绘制圆角矩形
    QRect rect(0, 0, width(), height());
    painter.drawRoundedRect(rect, 7, 7);
}

ViewData* FontUnit::getViewData()
{
    return m_viewData;
}

void FontUnit::setInstallFlag(bool flag)
{
    m_installFlag = flag;
    this->repaint();
}

void FontUnit::enterEvent(QEvent *event)
{
    m_isMouseOpt = true;
    this->repaint();
}

void FontUnit::leaveEvent(QEvent *event)
{
    m_isMouseOpt = false;
    this->repaint();
}
