/*
 * Copyright (C) 2023, 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 3 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, see <https://www.gnu.org/licenses/>.
 *
 */
#include "upm_controldbus.h"

Q_GLOBAL_STATIC(UpmControlDBus, s_controlDBus)

UpmControlDBus::UpmControlDBus(QObject *parent) : QObject(parent)
{
    m_userName = qgetenv("USER");
    if (m_userName.isEmpty()) {
        m_userName = qgetenv("USERNAME");
    }
    qDebug() << "current user:" << m_userName;

    controlPowerManagement(UPM_DBUS_METHOD_USER_LOGIN, m_userName);

    m_userActive = true;

    QDBusConnection::systemBus().connect(
                UPM_DBUS_SERVICE, UPM_DBUS_PATH, UPM_DBUS_INTERFACE,
                "SystemConfigChanged", this,
                SLOT(dealSystemConfigChanged(const QString, const QString, const QString)));
    QDBusConnection::systemBus().connect(
                UPM_DBUS_SERVICE, UPM_DBUS_PATH, UPM_DBUS_INTERFACE,
                "ActiveUserChanged", this,
                SLOT(dealActiveUserChanged(const QString)));
}

UpmControlDBus::~UpmControlDBus()
{
    controlPowerManagement(UPM_DBUS_METHOD_USER_LOGOUT, m_userName);
}

UpmControlDBus *UpmControlDBus::self()
{
    return s_controlDBus;
}

QString UpmControlDBus::getUserName()
{
    return m_userName;
}

void UpmControlDBus::setUserActive(bool userActive)
{
    m_userActive = userActive;
    if (true == userActive) {
        controlPowerManagement(UPM_DBUS_METHOD_USER_ACTIVE, m_userName);
    }
}

void UpmControlDBus::controlPowerManagement(const QString &method, QVariant parameter, bool effective)
{
    if (false == m_userActive) {
        return ;
    }

    QDBusInterface dBusInterface(UPM_DBUS_SERVICE,
                                 UPM_DBUS_PATH,
                                 UPM_DBUS_INTERFACE,
                                 QDBusConnection::systemBus());

    QVariant::Type valueType = parameter.type();
    if (true == effective) {
        if (QVariant::String == valueType) {
            dBusInterface.call(method, parameter.toString());
        } else if (QVariant::Int == valueType) {
            dBusInterface.call(method, parameter.toInt());
        } else if (QVariant::Bool == valueType) {
            dBusInterface.call(method, parameter.toBool());
        }
    } else {
        dBusInterface.call(method);
    }
}

QString UpmControlDBus::getUpmSystemConfig(const QString &key)
{
    QDBusInterface dBusInterface(UPM_DBUS_SERVICE,
                                 UPM_DBUS_PATH,
                                 UPM_DBUS_INTERFACE,
                                 QDBusConnection::systemBus());
    QDBusReply<QString> reply = dBusInterface.call(UPM_DBUS_METHOD_GET_SYS_CONFIG, key);
    if (reply.isValid()) {
        return reply.value();
    }
    return QString();
}

void UpmControlDBus::setUpmSystemConfig(const QString &key, const QString &value)
{
    if (false == m_userActive) {
        return ;
    }
    QDBusInterface dBusInterface(UPM_DBUS_SERVICE,
                                 UPM_DBUS_PATH,
                                 UPM_DBUS_INTERFACE,
                                 QDBusConnection::systemBus());
    dBusInterface.call(UPM_DBUS_METHOD_SET_SYS_CONFIG, m_userName, key, value);
}

void UpmControlDBus::setUpmBoolConfig(const QString &key, bool value)
{
    if (true == value) {
        setUpmSystemConfig(key, "true");
    } else {
        setUpmSystemConfig(key, "false");
    }
}


void UpmControlDBus::controlDisplay(const QString &action)
{
    if (false == m_userActive) {
        return ;
    }

    QString strCmd;
    if ("wayland" == qgetenv("XDG_SESSION_TYPE")) {
        strCmd = QString("export QT_QPA_PLATFORM=wayland && ");
        strCmd.append(QString("kscreen-doctor --dpms %1").arg(action));
    } else {
        strCmd = QString("xset dpms force %1").arg(action);
    }

    qDebug() << "The display:" << qgetenv("XDG_SESSION_TYPE")
             << "turn" << action;

    QProcess process;
    process.start("bash", QStringList() << "-c" << strCmd);
    process.waitForFinished();
}

void UpmControlDBus::turnOffDisplaySignal()
{
    const bool state = true;
    QDBusMessage msg = QDBusMessage::createSignal("/", "ukui.power.manager", "TurnOffDisplay");
    msg << state;
    QDBusConnection::sessionBus().send(msg);
    qDebug() << "send turn off display msg";
}

void UpmControlDBus::delayLockScreen(const QString &action)
{
    QString strCmd = QString("ukui-screensaver-command -b ");

    strCmd.append(action);

    QProcess process;
    //执行命令
    process.start(strCmd);
    //等待命令执行结束
    process.waitForFinished();
}

void UpmControlDBus::dealSystemConfigChanged(const QString userName, const QString key, const QString value)
{
    emit systemConfigChangedSignal(userName, key, value);
}

void UpmControlDBus::dealActiveUserChanged(const QString userName)
{
    if (userName != m_userName) {
        m_userActive = false;
    }
}
