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

UpmLid::UpmLid(QObject *parent) : QObject(parent)
{
    m_displayIsOn = true;
    m_lidIsClosed = UpmUpowerDBus::self()->getLidClosedState();

    initLidActionFun();

    QStringList valueRange = {UPM_POWER_ACTION_NOTHING, UPM_POWER_ACTION_BLANK,
                              UPM_POWER_ACTION_SUSPEND, UPM_POWER_ACTION_HIBERNATE,
                              UPM_POWER_ACTION_SHUTDOWN};
    m_closeLidActionAc = UpmCheckConfig::checkConfig(
                GSETTINGS_KEY_BUTTON_LID_AC,
                QString(UPM_POWER_ACTION_SUSPEND), QVariant::String,
                valueRange, false).toString();
    m_closeLidActionBattery = UpmCheckConfig::checkConfig(
                GSETTINGS_KEY_BUTTON_LID_BATTERY,
                UPM_POWER_ACTION_SUSPEND, QVariant::String,
                valueRange, false).toString();

    connect(UpmGsettings::self(), &UpmGsettings::buttonLidAcChanged,
            this, [=](QVariant value) {
        m_closeLidActionAc = value.toString();
        UpmControlDBus::self()->setUpmSystemConfig(GSETTINGS_KEY_BUTTON_LID_AC,
                                                   m_closeLidActionAc);
    });
    connect(UpmGsettings::self(), &UpmGsettings::buttonLidBatteryChanged,
            this, [=](QVariant value) {
        m_closeLidActionBattery = value.toString();
        UpmControlDBus::self()->setUpmSystemConfig(GSETTINGS_KEY_BUTTON_LID_BATTERY,
                                                   m_closeLidActionBattery);
    });
    connect(UpmCommonDBus::self(), &UpmCommonDBus::systemSleepStatus,
            this, &UpmLid::dealSystemSleepStatus);
    connect(UpmUpowerDBus::self(), &UpmUpowerDBus::lidStateChanged,
            this, &UpmLid::dealLidStateChanged);
}

void UpmLid::initLidActionFun()
{
    addLidActionFun(UPM_POWER_ACTION_NOTHING,   &UpmLid::closeLidNothingToDo);
    addLidActionFun(UPM_POWER_ACTION_BLANK,     &UpmLid::closeLidTurnOffDisplay);
    addLidActionFun(UPM_POWER_ACTION_SUSPEND,   &UpmLid::closeLidToSuspend);
    addLidActionFun(UPM_POWER_ACTION_HIBERNATE, &UpmLid::closeLidToHibernate);
    addLidActionFun(UPM_POWER_ACTION_SHUTDOWN,  &UpmLid::closeLidToShutdown);
}

void UpmLid::addLidActionFun(const QString &action, pCloseLidActionFun actionFun)
{
    m_closeLidActionFun[action] = actionFun;
}

void UpmLid::dealLidStateChanged(bool lidIsClosed)
{
    QString action;

    m_lidIsClosed = lidIsClosed;

    if (true == UpmUpowerDBus::self()->getAcOnlineState()) {
        action = m_closeLidActionAc;
    } else {
        action = m_closeLidActionBattery;
    }

    qDebug() << "lid state:" << m_lidIsClosed
             << "action:" << action;

    if (true == m_lidIsClosed) {
        (this->*m_closeLidActionFun[action])();
    } else {
        if("blank" == action && false == m_displayIsOn) {
            UpmControlDBus::self()->controlDisplay("on");
            m_displayIsOn = true;
        }
    }
}

void UpmLid::dealSystemSleepStatus(bool isSleep)
{
    if (isSleep) {
        qDebug() << "The computer is going to sleep";
    } else {
        if (m_lidIsClosed) {
            qWarning() << "Sleep is awakened unexpectedly!";
            dealLidStateChanged(m_lidIsClosed);
        } else {
            qDebug() << "The computer wakes up";
        }
    }
}

void UpmLid::closeLidNothingToDo() {}

void UpmLid::closeLidTurnOffDisplay()
{
    UpmControlDBus::self()->delayLockScreen("lid");
    UpmControlDBus::self()->controlDisplay("off");
    UpmControlDBus::self()->turnOffDisplaySignal();
    m_displayIsOn = false;
}

void UpmLid::closeLidToSuspend()
{
    UpmControlDBus::self()->controlPowerManagement("Suspend", 0, false);
}

void UpmLid::closeLidToShutdown()
{
    UpmControlDBus::self()->controlPowerManagement("PowerOff", 0, false);
}

void UpmLid::closeLidToHibernate()
{
    UpmControlDBus::self()->controlPowerManagement("Hibernate", 0, false);
}

