/* -*- 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 <QVBoxLayout>
#include <QHBoxLayout>
#include <QPushButton>
#include <QFrame>
#include <QLabel>
#include <QComboBox>
#include <QGSettings>
#include <QStandardItemModel>
#include <QFontDatabase>
#include <QDebug>
#include <QTextEdit>
#include "advanceddialog.h"
#include "lightlabel.h"
#include "ukcccommon.h"

using namespace ukcc;

#define INTERFACE_SCHEMA   "org.mate.interface"
#define DOC_FONT_KEY       "document-font-name"  // 用于阅读文档的默认字体的名称
#define GTK_FONT_KEY       "font-name"           // gkt+使用的默认字体
#define MONOSPACE_FONT_KEY "monospace-font-name" // 用于终端等处的等宽字体

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

#define UKCC_SCHEMA        "org.ukui.control-center"
#define UKCC_FONTS_EKY     "fonts-list"
#define GNOME_SCHEMA       "org.gnome.desktop.interface"

AdvancedDialog::AdvancedDialog(QWidget *parent) :
    QWidget(parent)
{
    this->setParent(parent);
    setWindowTitle(tr("Advanced set"));
    this->setFixedSize(424, 283);
    this->setWindowFlag(Qt::Tool);
    this->setWindowModality(Qt::WindowModal);
    this->setWindowModality(Qt::ApplicationModal);
    this->setAutoFillBackground(true);
    this->setBackgroundRole(QPalette::Base);
    this->setAttribute(Qt::WA_DeleteOnClose,true);

    const QByteArray id(INTERFACE_SCHEMA);
    m_ifsettings = new QGSettings(id, QByteArray(), this);

    const QByteArray gnomeID(GNOME_SCHEMA);
    m_gnomeSettings = new QGSettings(gnomeID, QByteArray(), this);

    const QByteArray styleID(STYLE_FONT_SCHEMA);
    m_stylesettings = new QGSettings(styleID, QByteArray(), this);

    setWidgetUi();
    setWidgetContent();
    setConnect();
}

QStringList AdvancedDialog::splitFontNameSize(QString value) {
    QStringList valueStringList;
    QString str = value.right(1);
    QString ch0 = static_cast<QString>('0');
    QString ch9 = static_cast<QString>('9');
    if (str >= ch0 && str <= ch9) {
        QStringList tmpStringList = value.split(' ');
        QString::SectionFlag flag = QString::SectionSkipEmpty;
        valueStringList << value.section(' ', 0, tmpStringList.length() - 2, flag);
        valueStringList << value.section(' ', tmpStringList.length() - 1, tmpStringList.length() - 1, flag);
    } else {
        valueStringList << value << "10";
    }
    return valueStringList;
}

AdvancedDialog::~AdvancedDialog()
{
    if (m_confirmButton) {
        delete m_confirmButton;
        m_confirmButton = nullptr;
    }
}

void AdvancedDialog::setWidgetUi()
{
    m_title = new QLabel(tr("Mono font"), this);
    QFont titleFont;
    titleFont.setFamily("Noto Sans CJK SC");
    titleFont.setBold(true);
    titleFont.setPixelSize(16);
    m_title->setFont(titleFont);
    m_title->setFixedHeight(24);

    m_desc = new QTextEdit(tr("Mono font refers to a font with the same character width, commonly used in programming to facilitate code alignment and improve code readability. Generally effective in applications that follow the system with equally wide fonts."), this);
    m_desc->setFixedWidth(376);
    m_desc->setReadOnly(true);
    m_desc->setTextColor(Qt::gray);
    QPalette paltte;
    paltte.setColor(QPalette::WindowText, paltte.placeholderText().color());
    m_desc->setPalette(paltte);
    QFont descFont;
    descFont.setFamily("Noto Sans CJK SC");
    descFont.setPixelSize(14);
    m_desc->setFont(descFont);

    static const int PREVIEW_WIDTH = 376;
    static const int PREVIEW_HEIGHT = 63;
    QFontMetrics fontMetrics(m_desc->font());
    QString descText = m_desc->toPlainText();
    int fontWidth = fontMetrics.width(descText);
    int fontLine = fontWidth / PREVIEW_WIDTH;
    if (fontWidth % PREVIEW_WIDTH != 0) {
        fontLine = fontLine + 1;
    }
    int fontHeight = fontMetrics.height();
    if (fontLine >= 3 && (3 * fontHeight > PREVIEW_HEIGHT)) {
        m_desc->setText(fontMetrics.elidedText(descText, Qt::ElideRight, 3 * PREVIEW_WIDTH - 64));
        m_desc->setToolTip(descText);
    }

    m_monoCombox = new QComboBox(this);
    m_monoCombox->setFixedWidth(380);
    m_monoCombox->setModel(new QStandardItemModel());

    m_monoModel = dynamic_cast<QStandardItemModel *>(m_monoCombox->model());

    m_confirmButton = new QPushButton(tr("Finish"));
    m_confirmButton->setProperty("isImportant", true);
    m_confirmButton->setFixedSize(88, 36);

    m_gridLayout = new QGridLayout(this);
    m_gridLayout->setHorizontalSpacing(1);
    m_gridLayout->setVerticalSpacing(0);
    m_gridLayout->setContentsMargins(24, 16, 24, 24);
    QLabel* label = new QLabel(this);
    label->setFixedHeight(50);
    m_gridLayout->addWidget(m_title, 0, 0, 1, 1, Qt::AlignLeft | Qt::AlignTop);
    m_gridLayout->addWidget(m_desc, 1, 0, 1, 1, Qt::AlignLeft | Qt::AlignTop);
    m_gridLayout->addWidget(m_monoCombox, 2, 0, 1, 1, Qt::AlignCenter | Qt::AlignTop);
    m_gridLayout->addWidget(label, 3, 0, 1, 1, Qt::AlignCenter | Qt::AlignTop);
    m_gridLayout->addWidget(m_confirmButton, 4, 0, 1, 1, Qt::AlignRight);

    m_vGridLayout = new QVBoxLayout(this);
    m_vGridLayout->addLayout(m_gridLayout);
    m_vGridLayout->addStretch();
    m_vGridLayout->setMargin(0);
    this->setLayout(m_vGridLayout);
    UkccCommon::centerToScreen(this);
}

void AdvancedDialog::setWidgetContent()
{
    QFontDatabase fontdb;
    QStringList fontfamiles = fontdb.families();
    for (QString fontValue : fontfamiles) {
        if (fontValue.contains("Mono") && !fontValue.contains("Ubuntu", Qt::CaseInsensitive)) {
            QStandardItem* monoItem = new QStandardItem(fontValue);
            monoItem->setFont(QFont(fontValue));
            m_monoModel->appendRow(monoItem);
        }
    }

    m_monospacefontStrList = splitFontNameSize(m_ifsettings->get(MONOSPACE_FONT_KEY).toString());

    QString currentmonofont = m_monospacefontStrList[0];
    if ("DejaVu sans Mono" == currentmonofont) {
        currentmonofont = "DejaVu Sans Mono";
    }
    m_monoCombox->blockSignals(true);
    m_monoCombox->setCurrentText(currentmonofont);
    m_monoCombox->blockSignals(false);
}

void AdvancedDialog::comboxTextChangedSlot(const QString& text)
{
    QVariant monoName = QVariant(QString("%1 %2").arg(text).arg(m_monospacefontStrList.at(1)));
    m_ifsettings->set(MONOSPACE_FONT_KEY, monoName);
    m_gnomeSettings->set(MONOSPACE_FONT_KEY, monoName);
    UkccCommon::buriedSettings("Font", text, QString("select"), monoName.toString());
}

void AdvancedDialog::styleSettingChangeSlot(const QString& key)
{
    if("systemFont" == key || "systemFontSize" == key) {
        m_monoCombox->setCurrentText(m_ifsettings->get(MONOSPACE_FONT_KEY).toString());
    }
}

void AdvancedDialog::monoSettingChangeSlot(const QString &key)
{
    if ("monospaceFontName" == key) {
        QString str = m_ifsettings->get(MONOSPACE_FONT_KEY).toString();
        m_monoCombox->setCurrentText(str.mid(0 , str.size() - 3));
    }
}

void AdvancedDialog::setConnect()
{
    connect(m_monoCombox, &QComboBox::currentTextChanged, [=](QString text) {
        comboxTextChangedSlot(text);
    });

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

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

    connect(m_confirmButton, &QPushButton::clicked, [=](bool checked){
        this->window()->close();
    });
}
