/*
 * Copyright (C) 2018 Tianjin KYLIN Information Technology 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, 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 <http://www.gnu.org/licenses/>.
 *
**/
#include "sessionwatcher.h"
#include <QDBusInterface>
#include <QDebug>
#include <QFile>
#include <QDBusReply>
#include "types.h"
#include "glibinterface.h"

#define GSETTINGS_SCHEMA_SCREENSAVER "org.ukui.screensaver"
#define KEY_IDLE_DELAY "idleDelay"
#define KEY_IDLE_LOCK "idleLock"
#define KEY_IDLE_ACTIVATION_ENABLED "idleActivationEnabled"
#define KEY_IDLE_LOCK_ENABLED "idleLockEnabled"
#define TIME_TYPE_SCHEMA 			"org.ukui.control-center.panel.plugins"
#define KEY_LOCK_TIMEOUT "lockTimeout"
#define STYLE_TYPE_SCHEMA 			"org.ukui.style"

#define GSETTINGS_SCHEMA_SCREENSAVER_DEFAULT "org.ukui.screensaver-default"
#define KEY_SHOW_REST_TIME "showRestTime"   // old
#define KEY_SHOW_CUSTOM_REST_TIME "showCustomRestTime"
#define KEY_SHOW_UKUI_REST_TIME "showUkuiRestTime"

#define POWER_TYPE_SCHENA                   "org.ukui.power-manager"
#define FREEDESKTOP_UPOWER                  "org.freedesktop.DBus.Properties"
#define UPOWER_PATH                         "/org/freedesktop/UPower"
#define UPOWER_SERVICE                      "org.freedesktop.UPower"
#define UPOWER_DISPLAY_PATH                 "/org/freedesktop/UPower/devices/DisplayDevice"
#define G_FONT_SIZE 			    (11.0)

SessionWatcher::SessionWatcher(QObject *parent) : QObject(parent)
{
    sessionPath = qgetenv("XDG_SESSION_PATH");

    defaultFontSize = getDefaultFontSize();

    QDBusInterface *interface = new QDBusInterface(
                SM_DBUS_SERVICE,
                SM_DBUS_PATH,
                SM_DBUS_INTERFACE,
                QDBusConnection::sessionBus(), this);

    connect(interface, SIGNAL(StatusChanged(unsigned int)),
            this, SLOT(onStatusChanged(unsigned int)));

    QDBusInterface *displayManagerInterface = new QDBusInterface(
                DM_DBUS_SERVICE,
                DM_DBUS_PATH,
                DM_DBUS_INTERFACE,
                QDBusConnection::systemBus(), this);
    connect(displayManagerInterface, SIGNAL(SessionRemoved(QDBusObjectPath)),
            this, SLOT(onSessionRemoved(QDBusObjectPath)));

    QStringList keysScreenSaver;
    if(QGSettings::isSchemaInstalled(GSETTINGS_SCHEMA_SCREENSAVER)){
        m_ssSettings = new QGSettings(GSETTINGS_SCHEMA_SCREENSAVER, "", this);
        connect(m_ssSettings, &QGSettings::changed,
                this, &SessionWatcher::onSSConfigChanged);
        keysScreenSaver = m_ssSettings->keys();
        // 重置屏保从不字段
        if (keysScreenSaver.contains(KEY_IDLE_ACTIVATION_ENABLED)) {
            bool isEnable = m_ssSettings->get("idle-activation-enabled").toBool();
            if (!isEnable) {
                m_ssSettings->set("idle-activation-enabled", true);
                if (keysScreenSaver.contains(KEY_IDLE_DELAY)) {
                    m_ssSettings->set("idle-delay", -1);
                }
            }
        }
        // 重置锁屏时间(不处理超时锁屏220620)
        if (keysScreenSaver.contains(KEY_IDLE_LOCK)) {
            m_ssSettings->set("idle-lock", -1);
        }
        idleDelay = m_ssSettings->get("idle-delay").toInt();
        idleLock = m_ssSettings->get("idle-lock").toInt();

        if (keysScreenSaver.contains(KEY_LOCK_TIMEOUT)) {
            m_nLockTimeout = m_ssSettings->get("lock-timeout").toInt();
        }
    }

    if(QGSettings::isSchemaInstalled(GSETTINGS_SCHEMA_SCREENSAVER_DEFAULT)){
        m_sdSettings = new QGSettings(GSETTINGS_SCHEMA_SCREENSAVER_DEFAULT, "", this);
        // 重置屏保休息时间字段
        QStringList keysScreenSaverDefault = m_sdSettings->keys();
        if (keysScreenSaverDefault.contains(KEY_SHOW_REST_TIME)) {
            bool isShow = m_sdSettings->get("show-rest-time").toBool();
            if (!isShow) {
                m_sdSettings->set("show-rest-time", true);
                if (keysScreenSaverDefault.contains(KEY_SHOW_CUSTOM_REST_TIME)) {
                    m_sdSettings->set("show-custom-rest-time", isShow);
                }
                if (keysScreenSaverDefault.contains(KEY_SHOW_UKUI_REST_TIME)) {
                    m_sdSettings->set("show-ukui-rest-time", isShow);
                }
            }
        }
    }

    // for PowerManager
    // 同步旧的电源管理唤醒是否需密码配置
    FILE *fp = NULL;
    fp = popen("xset s 0 0", "r");
    fclose(fp);

    if(QGSettings::isSchemaInstalled(POWER_TYPE_SCHENA)){
        m_pmSettings = new QGSettings(POWER_TYPE_SCHENA,"", this);
        QStringList keys = m_pmSettings->keys();
        if (keys.contains("lockSuspend")) {
            bool ret = m_pmSettings->get("lockSuspend").toBool();
            if(ret){
                m_pmSettings->set("lock-suspend",false);
            }
        }
        if (keys.contains("lockHibernate")) {
            bool ret = m_pmSettings->get("lockHibernate").toBool();
            if(ret){
                m_pmSettings->set("lock-hibernate",false);
            }
        }
        if (keys.contains("lockBlankScreen") && keysScreenSaver.contains("closeActivationEnabled")) {
            bool oldValue = m_pmSettings->get("lockBlankScreen").toBool();
            if(!oldValue && m_ssSettings){
                m_ssSettings->set("close-activation-enabled", oldValue);
                m_pmSettings->set("lock-blank-screen", true);
            }
        }
    }

    QString userName = getenv("USER");
    QString configPath;
    configPath = QString("/var/lib/lightdm-data/%1/ukui-greeter.conf").arg(userName);
    QFile fileConf(configPath);
    if (!fileConf.exists()) {
        QFile file(configPath);
        file.setPermissions(QFile::WriteUser | QFile::ReadUser | QFile::WriteOther | QFile::ReadOther);
    }
    configSettings = new QSettings(configPath, QSettings::IniFormat, this);
    if (QGSettings::isSchemaInstalled(TIME_TYPE_SCHEMA)) {
        timegsettings = new QGSettings(TIME_TYPE_SCHEMA,"",this);
        int timeType = timegsettings->get("hoursystem").toInt();
        setValue("timeType",timeType);
        QString dateType = timegsettings->get("date").toString();
        setValue("dateType",dateType);
        connect(timegsettings, &QGSettings::changed,
                this, &SessionWatcher::onConfigurationTimeTpChanged);
    }

    if (QGSettings::isSchemaInstalled(STYLE_TYPE_SCHEMA)) {
        stylesettings = new QGSettings(STYLE_TYPE_SCHEMA,"",this);
        double fontSize = stylesettings->get("systemFontSize").toDouble();
        setValue("fontSize",fontSize - defaultFontSize);
        connect(stylesettings, &QGSettings::changed,
                this, &SessionWatcher::onConfigurationTimeTpChanged);
    }

    // 监听合盖信号
    QDBusConnection::systemBus().connect(
            UPOWER_SERVICE, UPOWER_PATH, FREEDESKTOP_UPOWER, "PropertiesChanged", this, SLOT(onLidWatcherMessage(void)));
}

void SessionWatcher::onSSConfigChanged(QString strKey)
{
    if(strKey == KEY_IDLE_DELAY){
        idleDelay = m_ssSettings->get("idle-delay").toInt();
    } else if (strKey == KEY_IDLE_LOCK){
        idleLock = m_ssSettings->get("idle-lock").toInt();
    } else if (strKey == KEY_LOCK_TIMEOUT) {
        m_nLockTimeout = m_ssSettings->get("lock-timeout").toInt();
    }
}

void SessionWatcher::onConfigurationTimeTpChanged(QString key)
{
    if (key == "hoursystem") {
        int timeType = timegsettings->get("hoursystem").toInt();
        setValue("timeType",timeType);
    } else if (key == "date") {
        QString dateType = timegsettings->get("date").toString();
        setValue("dateType",dateType);
    } else if (key == "systemFontSize") {
        double fontSize = stylesettings->get("systemFontSize").toDouble()  - defaultFontSize;
        setValue("fontSize", fontSize);
    }
}

void SessionWatcher::setValue(const QString &key, const QVariant &value)
{
    if (!configSettings)
        return;
    configSettings->beginGroup("Greeter");
    configSettings->setValue(key, value);
    configSettings->endGroup();
}

void SessionWatcher::onStatusChanged(unsigned int status)
{
    if(status == SESSION_IDLE) {
        if(idleDelay != -1){
            if(!m_timer){
                m_timer = new QTimer(this);
                connect(m_timer, &QTimer::timeout, this, [&]{
                    Q_EMIT sessionIdle();
                    m_timer->stop();
                });
            }
            int time = (idleDelay - 1)*60000;
            if(time<0)
                time = 0;

            m_timer->start(time);
         }

        if(idleLock != -1){
            if(!m_timer2){
                m_timer2 = new QTimer(this);
                connect(m_timer2, &QTimer::timeout, this, [&]{
                    Q_EMIT sessionLockIdle();
                    m_timer2->stop();
                });
            }
            int lockTime = (idleLock - 1)*60000;
            if(lockTime<0)
                lockTime = 0;

            m_timer2->start(lockTime);
        }


    }else if(status == SESSION_AVAILABLE){
        if(m_timer && m_timer->isActive()){
            m_timer->stop();
        }
        if(m_timer2 && m_timer2->isActive()){
            m_timer2->stop();
        }
        Q_EMIT sessionIdleExit();
    }
}

void SessionWatcher::onSessionRemoved(const QDBusObjectPath &objectPath)
{
    //如果session注销了，则结束进程
    if(objectPath.path() == sessionPath)
        exit(0);
}

bool SessionWatcher::isSleepActivationEnable()
{
    if (!m_ssSettings)
        return false;
    QStringList settingsKeys = m_ssSettings->keys();
    if (settingsKeys.contains("sleepActivationEnabled")) {
        return m_ssSettings->get("sleep-activation-enabled").toBool();
    } else {
        return false;
    }
}

bool SessionWatcher::isCloseActivationEnable()
{
    if (!m_ssSettings)
        return false;
    QStringList settingsKeys = m_ssSettings->keys();
    if (settingsKeys.contains("closeActivationEnabled")) {
        return m_ssSettings->get("close-activation-enabled").toBool();
    } else {
        return false;
    }
}

bool SessionWatcher::isLockEnable()
{
    if (!m_ssSettings)
        return false;
    QStringList settingsKeys = m_ssSettings->keys();
    if (settingsKeys.contains("lockEnabled")) {
        return m_ssSettings->get("lock-enabled").toBool();
    } else {
        return false;
    }
}

int SessionWatcher::sleepActivationDelay()
{
    if (!m_pmSettings)
        return -1;
    QStringList settingsKeys = m_pmSettings->keys();
    if (settingsKeys.contains("sleepComputerAc")) {
        return m_pmSettings->get("sleep-computer-ac").toInt();
    } else {
        return -1;
    }
}

int SessionWatcher::closeActivationDelay()
{
    if (!m_pmSettings)
        return -1;
    QStringList settingsKeys = m_pmSettings->keys();
    if (settingsKeys.contains("sleepDisplayAc")) {
        return m_pmSettings->get("sleep-display-ac").toInt();
    } else {
        return -1;
    }
}

int SessionWatcher::idledelay()
{
    return idleDelay;
}

int SessionWatcher::locktimeout()
{
    return m_nLockTimeout;
}

bool SessionWatcher::isLidCloseWithBlank()
{
    if (!m_pmSettings)
        return false;
    QStringList settingsKeys = m_pmSettings->keys();
    if (settingsKeys.contains("buttonLidAc")) {
        QString strAction = m_pmSettings->get("button-lid-ac").toString();
        return (strAction == "blank");
    } else {
        return false;
    }
}

void SessionWatcher::onLidWatcherMessage(void)
{
    QDBusInterface iface(UPOWER_SERVICE, UPOWER_PATH, FREEDESKTOP_UPOWER, QDBusConnection::systemBus());
    QDBusReply<QVariant> reply = iface.call("Get", "org.freedesktop.UPower", "LidIsClosed");
    if (reply.isValid()) {
        m_lidState = reply.value().toBool();
        Q_EMIT lidStateChanged(m_lidState);
        qDebug() << "lid state:" << m_lidState;
    } else {
        qDebug() << "Failed to get lid closed event!";
    }
}
