/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 *
 * Copyright (C) 2025 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 "accessibility.h"
#include "accessibilityui.h"

#include <QDebug>
#include <kysdk/applications/accessinfohelper.h>
using namespace kdk;

#define UKUI_STYLE_ID                    "org.ukui.style"
#define UKUI_STYLE_NAME                  "style-name"

const QString m_filterPreview = ":/images/filterPreview.png";

Accessibility::Accessibility() : m_firstLoad(true)
{
    m_pluginName = tr("Accessibility");
    m_pluginType = COMMONINFO;
}

Accessibility::~Accessibility()
{
}

QString Accessibility::plugini18nName()
{
    return m_pluginName;
}

int Accessibility::pluginTypes()
{
    return m_pluginType;
}

QWidget *Accessibility::pluginUi()
{
    if (m_firstLoad) {
        m_firstLoad = false;

        ui = new Ui::Accessibility;
        m_pPluginWidget = new QWidget;
        m_pPluginWidget->setAttribute(Qt::WA_DeleteOnClose);
        ui->setupUi(m_pPluginWidget);
        ui->m_pZoomLabel_1->setFixedHeight(ui->m_pZoomLabel_1->height() + 1);

        initUI();
        initQGSettingsAndDBus();
        initDefaultData();
        initConnection();
    }
    return m_pPluginWidget;
}

const QString Accessibility::name() const
{
    return QStringLiteral("Accessibility");
}

bool Accessibility::isShowOnHomePage() const
{
    return true;
}

QIcon Accessibility::icon() const
{
    return QIcon::fromTheme("preferences-desktop-accessibility-symbolic");
}

bool Accessibility::isEnable() const
{
    return true;
}

void Accessibility::initUI()
{
    m_pZoomSwitchButton    = new KSwitchButton(ui->m_pZoomFrame);
    m_pFilterSwitchButton   = new KSwitchButton(ui->m_pFilterFrame);
    m_pShortcutSwitchButton = new KSwitchButton(ui->m_pShortcutFrame);
    KDK_EXTEND_ALL_INFO_FORMAT(m_pZoomSwitchButton, name(), "", "");
    KDK_EXTEND_ALL_INFO_FORMAT(m_pFilterSwitchButton, name(), "", "");
    KDK_EXTEND_ALL_INFO_FORMAT(m_pShortcutSwitchButton, name(), "", "");

    ui->m_pZoomHorizontalLayout->addWidget(m_pZoomSwitchButton, 0, Qt::AlignRight);
    ui->m_pFilterHorizontalLayout->addWidget(m_pFilterSwitchButton, 0, Qt::AlignRight);
    ui->m_pShortcutHorizontalLayout->addWidget(m_pShortcutSwitchButton, 0, Qt::AlignRight);

    Q_ASSERT(!m_filterPreview.isNull());
    QPixmap filterViewPixmap(QIcon(m_filterPreview).pixmap(380,110));
    ui->m_pEffectPixmapLabel->setPixmap(filterViewPixmap);

    ui->m_pZoomComboBox->addItem(tr("Window Zoom"));
    ui->m_pZoomComboBox->addItem(tr("Full Screen Zoom"));

    ui->m_pFilterComboBox->addItem(tr("Red/Green Filter (Protanopia)"), QVariant("Protanopia"));
    ui->m_pFilterComboBox->addItem(tr("Green/Red Filter (Deuteranopia)"), QVariant("Deuteranopia"));
    ui->m_pFilterComboBox->addItem(tr("Blue/Yellow Filter (Tritanopia)"), QVariant("Tritanopia"));
    ui->m_pFilterComboBox->addItem(tr("Grayscale"), QVariant("GrayScale"));
    ui->m_pFilterComboBox->addItem(tr("Invert"), QVariant("Invert"));

    renewZoomLabel_2Palette();
}

void Accessibility::initConnection() {
    connect(ui->m_pZoomComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setZoomMode(int)));
    connect(ui->m_pFilterComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setFilterMode(int)));

    connect(m_pZoomSwitchButton, &KSwitchButton::toggled, this, &Accessibility::setZoomSwitch);
    connect(m_pFilterSwitchButton, &KSwitchButton::toggled, this, &Accessibility::setFilterSwitch);
    connect(m_pShortcutSwitchButton, &KSwitchButton::toggled, this, &Accessibility::setShortcutSwitch);

    connect(ui->m_pPointerSetBtn, &QPushButton::clicked, this, [=](){
        UkccCommon::buriedSettings(name(), "setBtn(Mouse)", QString("clicked"));
        QProcess::startDetached("ukui-control-center", QStringList() << "-m" << "Mouse");
    });
    connect(ui->m_pVocalSetBtn, &QPushButton::clicked, this, [=](){
        UkccCommon::buriedSettings(name(), "setBtn(Audio)", QString("clicked"));
        QProcess::startDetached("ukui-control-center", QStringList() << "-m" << "Audio");
    });
    const QByteArray id(UKUI_STYLE_ID);
    QGSettings* styleSettings  = new QGSettings(id, QByteArray(), this);
    connect(styleSettings, &QGSettings::changed, this, [=, styleSettings](const QString &key) {
        if (nullptr == styleSettings || key != "styleName") {
            return;
        }
        ui->m_pZoomLabel_2->setFontColor(ThemeController::getCustomColorFromDT("kfont-secondary"));
    });

    QDBusConnection::sessionBus().connect("org.ukui.ukcc.session",
                                          "/Accessibility",
                                          "org.ukui.ukcc.session.Accessibility",
                                          "statusChanged",
                                          this,
                                          SLOT(syncZoomSwitch(bool)));
    QDBusConnection::sessionBus().connect("org.ukui.ukcc.session",
                                          "/Accessibility",
                                          "org.ukui.ukcc.session.Accessibility",
                                          "modeChanged",
                                          this,
                                          SLOT(syncZoomComboBox(int)));
    QDBusConnection::sessionBus().connect("org.ukui.ukcc.session",
                                          "/Accessibility",
                                          "org.ukui.ukcc.session.Accessibility",
                                          "colorFilterTypeChanged",
                                          this,
                                          SLOT(syncFilterComboBox(QString)));
    QDBusConnection::sessionBus().connect("org.ukui.ukcc.session",
                                          "/Accessibility",
                                          "org.ukui.ukcc.session.Accessibility",
                                          "filterStatusChanged",
                                          this,
                                          SLOT(syncFilterSwitch(bool)));
    QDBusConnection::sessionBus().connect("org.ukui.ukcc.session",
                                          "/Accessibility",
                                          "org.ukui.ukcc.session.Accessibility",
                                          "colorFilterShortCutEnabledChanged",
                                          this,
                                          SLOT(syncShortcutSwitch(bool)));
}

void Accessibility::dataChanged(QString key)
{
    if (key == STYLE_NAME_CHANGE_KEY) {
        QString styleName = m_accessibilityInterface->property("styleName").toString();
        int disColor = COLOR_BALCK_NUMBER;
        if (styleName == "ukui-light") {
            disColor = COLOR_WHITE_NUMBER;
        }
        QPalette zoomLabelPalette;
        zoomLabelPalette.setColor(QPalette::WindowText, QColor(COLOR_WHITE_NUMBER - disColor,
                                                               COLOR_WHITE_NUMBER - disColor,
                                                               COLOR_WHITE_NUMBER - disColor,
                                                               ZOOM_LABEL_TRANSPARENT));
        ui->m_pZoomLabel_2->setPalette(zoomLabelPalette);
    }
}

void Accessibility::initQGSettingsAndDBus() {
    m_accessibilityInterface = new QDBusInterface("org.ukui.ukcc.session",
                                                  "/Accessibility",
                                                  "org.ukui.ukcc.session.Accessibility",
                                                  QDBusConnection::sessionBus(), this);
    if (!m_accessibilityInterface) {
        qCritical() << Q_FUNC_INFO << "org.ukui.ukcc.session.Accessibility QDBusInterface is null";
        return;
    }

    QDBusConnection::sessionBus().connect("org.ukui.ukcc.session",
                                          "/Accessibility",
                                          "org.ukui.ukcc.session.Accessibility",
                                          "changed",
                                          this,
                                          SLOT(dataChanged(QString)));
    m_pZoomSwitchButton->setChecked(false);
    QDBusReply<bool> isZoomingReply = m_accessibilityInterface->call("isZooming");
    qDebug() << Q_FUNC_INFO << "isZoomingReply" << isZoomingReply.isValid() << "isZooming" << isZoomingReply.value();
    if (isZoomingReply.isValid()) {
        m_pZoomSwitchButton->setChecked(isZoomingReply.value());
        qDebug() << Q_FUNC_INFO << "ZoomSwitchButton" << isZoomingReply.value();
    }
}

void Accessibility::initDefaultData() {
    QDBusReply<int> zoomModeReply = m_accessibilityInterface->call("GetType");
    qDebug() << Q_FUNC_INFO << "getZoomMode" << zoomModeReply.isValid() << "isZooming" << zoomModeReply.value();
    if (zoomModeReply.isValid()) {
        int index = zoomModeReply.value();
        if (index >= 0 && index < ui->m_pZoomComboBox->count()) {
            if (index == 0) {
                ui->m_pZoomComboBox->setCurrentIndex(1);
            } else {
                ui->m_pZoomComboBox->setCurrentIndex(0);
            }
        }
        qDebug() << Q_FUNC_INFO << "ZoomComboBox set index" << index;
    }

    QDBusReply<bool> effectReply = m_accessibilityInterface->call("isEffectSupported");
    qDebug() << Q_FUNC_INFO << "isEffectSupported valid" << effectReply.isValid() << effectReply.value();
    if (effectReply.isValid()){
        ui->m_pColorFrame->setVisible(effectReply.value());
    } else {
        ui->m_pColorFrame->setVisible(false);
    }

    QDBusReply<bool> shortcutReply = m_accessibilityInterface->call("isColorFilterShortCutEnabled");
    qDebug() << Q_FUNC_INFO << "isColorFilterShortCutEnabled" << shortcutReply.value();
    if (shortcutReply.isValid()){
        m_pShortcutSwitchButton->setChecked(shortcutReply.value());
    }

    QDBusReply<bool> enableReply = m_accessibilityInterface->call("isColorFilterEnabled");
    qDebug() << Q_FUNC_INFO << "isColorFilterEnabled" << enableReply.value();
    if (enableReply.isValid()){
        m_pFilterSwitchButton->setChecked(enableReply.value());
        ui->m_pFilterComboBox->setEnabled(enableReply.value());
    } else {
        m_pFilterSwitchButton->setChecked(false);
        ui->m_pFilterComboBox->setEnabled(false);
    }

    QDBusReply<QString> modeReply = m_accessibilityInterface->call("getCurrentColorFilter");
    qDebug() << Q_FUNC_INFO << "getCurrentColorFilter" << modeReply.value();
    if (modeReply.isValid()){
        QString filterMode = modeReply.value();
        for (int i = 0; i < ui->m_pFilterComboBox->count(); i++) {
            if (ui->m_pFilterComboBox->itemData(i) != filterMode) {
                continue;
            } else {
                ui->m_pFilterComboBox->setCurrentIndex(i);
                break;
            }
        }
    }
}

void Accessibility::renewZoomLabel_2Palette() {
    QPalette zoomLabelPalette = ui->m_pZoomLabel_2->palette();
    QColor zoomLabelColor = zoomLabelPalette.color(QPalette::WindowText);
    zoomLabelColor.setAlpha(ZOOM_LABEL_TRANSPARENT);
    zoomLabelPalette.setColor(QPalette::WindowText, zoomLabelColor);
    ui->m_pZoomLabel_2->setPalette(zoomLabelPalette);
}

void Accessibility::setZoomMode(int index) {
    qDebug() << Q_FUNC_INFO << "setZoomMode" << index;
    int dbusMode = 1;
    if (index == 1) {
        dbusMode = 0;
    }
    m_accessibilityInterface->asyncCall("setZoomMode", dbusMode);
}

void Accessibility::setFilterMode(int index) {
    qDebug() << Q_FUNC_INFO << "setColorFilter" << index << ui->m_pFilterComboBox->currentData();
    m_accessibilityInterface->asyncCall("setColorFilter", QVariant(ui->m_pFilterComboBox->currentData()));
}

void Accessibility::setZoomSwitch(bool toggled) {
    qDebug() << Q_FUNC_INFO << "setZoomSwitch" << toggled;
    m_accessibilityInterface->asyncCall("setZoomSwitch", toggled);
}

void Accessibility::setFilterSwitch(bool toggled) {
    qDebug() << Q_FUNC_INFO << "setFilterSwitch" << toggled;
    ui->m_pFilterComboBox->setEnabled(toggled);
    m_accessibilityInterface->asyncCall("setColorFilterSwitch", toggled);
}

void Accessibility::setShortcutSwitch(bool enabled) {
    qDebug() << Q_FUNC_INFO << "setColorFilterShortCutEnabled" << enabled;
    m_accessibilityInterface->asyncCall("setColorFilterShortCutEnabled", enabled);
}

void Accessibility::syncZoomSwitch(bool status) {
    qDebug() << Q_FUNC_INFO << status << __LINE__;
    if (status == m_pZoomSwitchButton->isChecked()) {
        return;
    }
    m_zoomSwitchSync = true;
    m_pZoomSwitchButton->setChecked(status);
}

void Accessibility::syncFilterSwitch(bool status) {
    qDebug() << Q_FUNC_INFO << __LINE__ << status;
    if (status == m_pFilterSwitchButton->isChecked()) {
        return;
    }
    m_pFilterSwitchButton->setChecked(status);
}

void Accessibility::syncShortcutSwitch(bool status) {
    qDebug() << Q_FUNC_INFO << __LINE__ << status;
    if (status == m_pShortcutSwitchButton->isChecked()) {
        return;
    }
    m_pShortcutSwitchButton->setChecked(status);
}

void Accessibility::syncZoomComboBox(int mode) {
    if (mode >= 0 && mode < ui->m_pZoomComboBox->count()) {
        if (mode == 0) {
            ui->m_pZoomComboBox->setCurrentIndex(1);
        } else {
            ui->m_pZoomComboBox->setCurrentIndex(0);
        }
    }
}

void Accessibility::syncFilterComboBox(QString type) {
    for (int i = 0; i < ui->m_pFilterComboBox->count(); i++) {
        if (ui->m_pFilterComboBox->itemData(i) != type) {
            continue;
        } else {
            ui->m_pFilterComboBox->setCurrentIndex(i);
            break;
        }
    }
}
