/* -*- 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 "ukccsessionserver.h"

#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QDebug>
#include <QDBusInterface>
#include <QDBusReply>

const QStringList openkylinFilterPathList = {"/Shortcut/Add", "/Shortcut/Customize Shortcut"};

ukccSessionServer::ukccSessionServer():UKUI::ServiceObject(nullptr)
{
   monitoFileChanged();
}

QMap<QString, QVariant> ukccSessionServer::getJsonInfo(const QString &configFile)
{
    QVariantMap moduleMap;

    QFile file(configFile);
    if (file.exists()) {
        file.open(QIODevice::ReadOnly);
        QByteArray readBy=file.readAll();
        QJsonParseError error;
        QJsonDocument readDoc=QJsonDocument::fromJson(readBy,&error);
        QJsonArray obj=readDoc.object().value("ukcc").toArray();

        for (int i = 0 ; i < obj.size(); i++) {
            QJsonObject faObj= obj[i].toObject();
            if (!faObj.contains("name")) {
                continue;
            }
            if (!faObj.contains("visible")) {
                moduleMap.insert(faObj["name"].toString(), true);
            } else {
                moduleMap.insert(faObj["name"].toString(), faObj["visible"].toVariant());
            }

            QJsonArray childNodeAry =  faObj["childnode"].toArray();
            for (int j = 0; j < childNodeAry.size(); j++) {
                QJsonObject childObj = childNodeAry.at(j).toObject();
                QString modeName = childObj.value("name").toString();
                QString modeSet = modeName + "Settings";
                QVariant modeVisiable = childNodeAry.at(j).toObject().value("visible").toVariant();
                QString modeEnable = modeName +"Enable";
                QString modeEnableList = childNodeAry.at(j).toObject().value(modeEnable).toString();

                if (childObj.contains(modeName)) {
                    moduleMap.insert(modeName, modeVisiable);
                }
                if (childObj.contains(modeSet)) {
                    moduleMap.insert(modeSet, childNodeAry.at(j).toObject().value(modeSet).toString());
                }
                if (childObj.contains(modeEnable)) {
                    moduleMap.insert(modeEnable, modeEnableList);
                }

                if (modeName.contains("autoboot")) {
                    moduleMap.insert(QString("autostart"), modeVisiable);
                }

                if (modeSet.contains("autobootSettings")) {
                    moduleMap.insert(QString("autostartSettings"), childNodeAry.at(j).toObject().value(modeSet).toString());
                }

                if (modeEnable.contains("autobootEnable")) {
                    if (modeEnableList.contains("autobootAllPage")) {
                        modeEnableList.replace("autobootAllPage", QString("autostartAllPage"), Qt::CaseInsensitive);
                    }
                    moduleMap.insert(QString("autostartEnable"), modeEnableList);
                }


                if (modeName.contains("biometrics")) {
                    moduleMap.insert(QString("login options"), modeVisiable);
                }

                if (modeSet.contains("biometricsSettings")) {
                    moduleMap.insert(QString("login optionsSettings"), childNodeAry.at(j).toObject().value(modeSet).toString());
                }

                if (modeEnable.contains("biometricsEnable")) {
                    if (modeEnableList.contains("biometricsAllPage")) {
                        modeEnableList.replace("login optionsAllPage", QString("login optionsAllpage"), Qt::CaseInsensitive);
                    }
                    moduleMap.insert(QString("login optionsEnable"), modeEnableList);
                }


                if (modeName.contains("defaultapp")) {
                    moduleMap.insert(QString("default"), modeVisiable);
                }

                if (modeSet.contains("defaultappSettings")) {
                    moduleMap.insert(QString("defaultSettings"), childNodeAry.at(j).toObject().value(modeSet).toString());
                }

                if (modeEnable.contains("defaultappEnable")) {
                    if (modeEnableList.contains("defaultappAllPage")) {
                        modeEnableList.replace("defaultappAllPage", QString("defaultAllPage"), Qt::CaseInsensitive);
                    }
                    moduleMap.insert(QString("defaultEnable"), modeEnableList);
                }
            }
        }
    }
    return moduleMap;
}

QString ukccSessionServer::getScreenMode()
{
    return mScreenMode;
}

void ukccSessionServer::setScreenMode(QString screenMode)
{
    mScreenMode = screenMode;
    Q_EMIT screenChanged(mScreenMode);
}

void ukccSessionServer::exitService()
{
    this->emitUkuiServiceObjectFinished();
}

void ukccSessionServer::ReloadSecurityConfig()
{
    qDebug() << "Reload Security Config";
    Q_EMIT configChanged();
}

QVariantMap ukccSessionServer::getModuleHideStatus()
{
    QString userFilename = QDir::homePath() + "/.config/ukui-control-center-security-config.json";
    QString systemFilename = "/usr/share/ukui-control-center/data/ukui-control-center-security-config.json";

    QMap<QString, QVariant> userConfig   = getJsonInfo(userFilename);
    QMap<QString, QVariant> systemConfig = getJsonInfo(systemFilename);

    if (userConfig.isEmpty()) return systemConfig;

    for (QString key : systemConfig.keys()) {
        if (userConfig.value(key) == "" && systemConfig.value(key) != "") {
            userConfig[key] = systemConfig.value(key);
        }
    }
    return userConfig;
}

QString ukccSessionServer::GetSecurityConfigPath()
{
    // usd 管控文件是否存在，若存在使用 usd 管控文件
    QDBusInterface usdDbus("org.ukui.SettingsDaemon",
                           "/GlobalSignal",
                           "org.ukui.SettingsDaemon.GlobalSignal",
                            QDBusConnection::sessionBus());
    QDBusReply<QStringList> res = usdDbus.call("getAPPSecurityConfigPath", "ukui-control-center");

    QStringList usdFileName = res;

    if (!usdFileName.isEmpty()) {
        return usdFileName.value(0);
    }

    QString systemFilename = "/usr/share/ukui-control-center/data/ukui-control-center-security-config.json";
    QFile file(systemFilename);
    if (file.exists()) {
        return systemFilename;
    }

    QString userFilename = QDir::homePath() + "/.config/ukui-control-center-security-config.json";
    QFile userFile(userFilename);
    if (userFile.exists()) {
        return userFilename;
    }

    QString moduleFileName = "/usr/share/ukui-control-center/data/ukui-control-center-config.json";
    return moduleFileName;
}

void ukccSessionServer::monitoFileChanged()
{
    QFileSystemWatcher *m_FileWatcher = new QFileSystemWatcher(this);
    m_FileWatcher->addPath(GetSecurityConfigPath());
    connect(m_FileWatcher, &QFileSystemWatcher::fileChanged, this, [=](){
        Q_EMIT configChanged();
    });

    QDBusConnection::systemBus().connect(QString(), QString("/securityConfig"), "com.kylin.ukui.SettingsDaemon.interface", "configChanged",
                                         this, SLOT(ReloadSecurityConfig()));
}

QVariantMap ukccSessionServer::getSearchItems()
{
    QDBusInterface* m_interface = new QDBusInterface("org.ukui.ukcc.search",
                                                     "/",
                                                     "org.ukui.ukcc.search.interface",
                                                     QDBusConnection::sessionBus(),
                                                     this);
    QJsonArray searchItems;
    QJsonObject rootobj;
    rootobj.insert("ukcc", searchItems);
    QJsonDocument document;
    document.setObject(rootobj);
    if (!m_interface->isValid()) {
        qDebug() << "ukcc search Interface Failed : " << QDBusConnection::sessionBus().lastError();
        return rootobj.toVariantMap();
    }
    QDBusReply<QVariantMap> reply = m_interface->call("getSearchItems");
    if (reply.isValid()) {
        return reply.value();
    } else {
        return rootobj.toVariantMap();
    }
}

