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

UpmLowPower::UpmLowPower(QObject *parent) : QObject(parent)
{
    QStringList valueRange = {QString::number(10), QString::number(20),
                              QString::number(30), QString::number(40)};
    m_percentageLow = UpmCheckConfig::checkConfig(
                GSETTINGS_KEY_PERCENTAGE_LOW,
                DEFAULE_PERCENTAGE_LOW, QVariant::Int,
                valueRange, false).toInt();

    valueRange.clear();
    valueRange << QString::number(5) << QString::number(9);
    m_percentageAction = UpmCheckConfig::checkConfig(
                GSETTINGS_KEY_PERCENTAGE_ACTION,
                DEFAULE_PERCENTAGE_ACTION, QVariant::Int,
                valueRange, true).toInt();

    valueRange.clear();
    valueRange << UPM_POWER_ACTION_NOTHING
               << UPM_POWER_ACTION_HIBERNATE
               << UPM_POWER_ACTION_SHUTDOWN;
    UpmCheckConfig::checkConfig(
                GSETTINGS_KEY_ACTION_CRITICAL_BATTERY,
                UPM_POWER_ACTION_HIBERNATE, QVariant::String,
                valueRange, false);

    valueRange.clear();
    valueRange << "true" << "false";
    m_enableBatterySaver = UpmCheckConfig::checkConfig(
                GSETTINGS_KEY_BATTERY_SAVE_SWITCH,
                false, QVariant::Bool,
                valueRange, false).toBool();
    m_autoEnableBatterySaver = UpmCheckConfig::checkConfig(
                GSETTINGS_KEY_LOW_BATTERY_AUTO_SAVE,
                false, QVariant::Bool,
                valueRange, false).toBool();
    m_enableReduceBrightness = UpmCheckConfig::checkConfig(
                GSETTINGS_KEY_BATTERY_SAVE_REDUCE_BRIGHTNESS,
                false, QVariant::Bool,
                valueRange, false).toBool();

    connect(UpmGsettings::self(), &UpmGsettings::percentageLowChanged,
            this, &UpmLowPower::dealPercentageLowChanged);
    connect(UpmGsettings::self(), &UpmGsettings::percentageActionChanged,
            this, &UpmLowPower::dealPercentageActionChanged);
    connect(UpmGsettings::self(), &UpmGsettings::actionCriticalBatteryChanged,
            this, [=](QVariant value) {
        UpmControlDBus::self()->setUpmSystemConfig(GSETTINGS_KEY_ACTION_CRITICAL_BATTERY,
                                                   value.toString());
    });

    connect(UpmGsettings::self(), &UpmGsettings::batterySaveSwitchChanged,
            this, &UpmLowPower::dealBatterySaveSwitchChanged);
    connect(UpmGsettings::self(), &UpmGsettings::lowBatteryAutoSaveChanged,
            this, &UpmLowPower::dealLowBatteryAutoSaveChanged);
    connect(UpmGsettings::self(), &UpmGsettings::batterySaveReduceBrightnessChanged,
            this, &UpmLowPower::dealBatterySaveReduceBrightnessChanged);

    connect(UpmUpowerDBus::self(), &UpmUpowerDBus::acOnlineStateChanged,
            this, &UpmLowPower::dealAcOnlineStateChanged);

    connect(UpmUpowerDBus::self(), &UpmUpowerDBus::batteryInfoChanged,
            this, &UpmLowPower::dealBatteryInfoChanged);

    if (true == UpmUpowerDBus::self()->getAcOnlineState()) {
        UpmGsettings::self()->setGsettingsConfig(GSETTINGS_KEY_BATTERY_SAVE_SWITCH, false);
    } else {
        if (true == m_enableBatterySaver) {
            UpmGsettings::self()->setGsettingsConfig(GSETTINGS_KEY_BATTERY_SAVE_SWITCH, true);
        }
    }
}

int UpmLowPower::getPowerPolicyBattery(const QString &configName)
{
    QVariant value;
    if (true == UpmGsettings::self()->getGsettingsConfig(configName, value)) {
        return value.toInt();
    } else {
        return power_policy_unknown;
    }
}

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

void UpmLowPower::dealPercentageLowChanged(QVariant value)
{
    m_percentageLow = value.toInt();
    UpmControlDBus::self()->setUpmSystemConfig(GSETTINGS_KEY_PERCENTAGE_LOW,
                                               QString::number(m_percentageLow));
    double percentage = UpmUpowerDBus::self()->getBatteryPercentage();
    if (false == m_batteryLowState) {
        if (m_percentageLow >= percentage && percentage > m_percentageAction) {
            m_batteryLowState = true;
            m_notificationId = UpmCommonDBus::self()->sendNotification(
                        tr("Low battery notification"),
                        tr("The system enters a low battery state"), true);
//            UpmCommonDBus::self()->playSystemSound(BATTERY_LOW);
            if (true == m_autoEnableBatterySaver) {
                UpmGsettings::self()->setGsettingsConfig(GSETTINGS_KEY_BATTERY_SAVE_SWITCH, true);
            }
            emit percentageLowSignal(true);
        }
    } else {
        if (percentage > m_percentageLow) {
            batteryPercentageRecoveryAction();
        }
    }
}

void UpmLowPower::dealPercentageActionChanged(QVariant value)
{
    m_percentageAction = value.toInt();
    UpmControlDBus::self()->setUpmSystemConfig(GSETTINGS_KEY_PERCENTAGE_ACTION,
                                      QString::number(m_percentageAction));
}

void UpmLowPower::dealBatterySaveSwitchChanged(QVariant value)
{
    int policy = power_policy_unknown;
    m_enableBatterySaver = value.toBool();
    setUpmSystemConfig(GSETTINGS_KEY_BATTERY_SAVE_SWITCH,
                       m_enableBatterySaver);
    if (true == m_enableBatterySaver) {
        policy = getPowerPolicyBattery(GSETTINGS_KEY_POWER_POLICY_BATTERY);
        UpmGsettings::self()->setGsettingsConfig(
                    GSETTINGS_KEY_POWER_POLICY_BATTERY_BACKUP, policy);
        UpmGsettings::self()->setGsettingsConfig(
                    GSETTINGS_KEY_POWER_POLICY_BATTERY, power_policy_powersave);
        if (true == m_enableReduceBrightness) {
            UpmControlDBus::self()->controlPowerManagement(
                        UPM_DBUS_METHOD_SET_REDUCE_BACKLIGHT_SWITCH, true);
        }
    } else {
        policy = getPowerPolicyBattery(GSETTINGS_KEY_POWER_POLICY_BATTERY_BACKUP);
        UpmGsettings::self()->setGsettingsConfig(GSETTINGS_KEY_POWER_POLICY_BATTERY_BACKUP,
                                                 power_policy_unknown);
        if (power_policy_powersave != policy) {
            UpmGsettings::self()->setGsettingsConfig(GSETTINGS_KEY_POWER_POLICY_BATTERY, policy);
        }
        if (true == m_enableReduceBrightness) {
            UpmControlDBus::self()->controlPowerManagement(
                        UPM_DBUS_METHOD_SET_REDUCE_BACKLIGHT_SWITCH, false);
        }
    }
}

void UpmLowPower::dealLowBatteryAutoSaveChanged(QVariant value)
{
    m_autoEnableBatterySaver = value.toBool();
    setUpmSystemConfig(GSETTINGS_KEY_LOW_BATTERY_AUTO_SAVE,
                       m_autoEnableBatterySaver);
    if (true == m_enableBatterySaver) {
        return ;
    }

    if (true == m_autoEnableBatterySaver && true == m_batteryLowState) {
        UpmGsettings::self()->setGsettingsConfig(GSETTINGS_KEY_BATTERY_SAVE_SWITCH, true);
    }
}

void UpmLowPower::dealBatterySaveReduceBrightnessChanged(QVariant value)
{
    m_enableReduceBrightness = value.toBool();
    setUpmSystemConfig(GSETTINGS_KEY_BATTERY_SAVE_REDUCE_BRIGHTNESS,
                       m_enableReduceBrightness);
    if (false == m_enableReduceBrightness) {
        if (true == m_enableBatterySaver) {
            UpmControlDBus::self()->controlPowerManagement(
                        UPM_DBUS_METHOD_SET_REDUCE_BACKLIGHT_SWITCH, false);
        }
        return ;
    }

    if (true == m_enableBatterySaver) {
        UpmControlDBus::self()->controlPowerManagement(
                    UPM_DBUS_METHOD_SET_REDUCE_BACKLIGHT_SWITCH, true);
    }
}

bool UpmLowPower::getBatterySaveSwitch(void)
{
    return m_enableBatterySaver;
}

bool UpmLowPower::getBatteryLowState(void)
{
    return m_batteryLowState;
}

void UpmLowPower::batteryPercentageLowAction()
{
    if (false == m_batteryLowState) {
        double percentage = UpmUpowerDBus::self()->getBatteryPercentage();
        if (m_percentageLow >= percentage && percentage > m_percentageAction) {
            m_batteryLowState = true;
            m_notificationId = UpmCommonDBus::self()->sendNotification(tr("Low battery notification"),
                                             tr("The system enters a low battery state"), true);
//            UpmCommonDBus::self()->playSystemSound(BATTERY_LOW);
            if (true == m_autoEnableBatterySaver) {
                UpmGsettings::self()->setGsettingsConfig(GSETTINGS_KEY_BATTERY_SAVE_SWITCH, true);
            }
            emit percentageLowSignal(true);
        }
    }
}

void UpmLowPower::batteryPercentageRecoveryAction()
{
    if (true == m_batteryLowState) {
        m_batteryLowState = false;
        UpmCommonDBus::self()->closeNotification(m_notificationId);
        m_notificationId = 0;
        if (true == m_enableBatterySaver) {
            UpmGsettings::self()->setGsettingsConfig(GSETTINGS_KEY_BATTERY_SAVE_SWITCH, false);
        }
        emit percentageLowSignal(false);
    }
}

void UpmLowPower::dealAcOnlineStateChanged(int index, bool acOnline)
{
    qDebug() << "ac index:" << index
             << "ac online state :" << acOnline;
    if (true == UpmUpowerDBus::self()->getAcOnlineState()) {
        batteryPercentageRecoveryAction();
    } else {
        batteryPercentageLowAction();
    }
}

void UpmLowPower::dealBatteryInfoChanged(int index, QStringList batteryInfo)
{
    qDebug() << "battery index:" << index
             << "battery online state :" << batteryInfo;
    if (false == UpmUpowerDBus::self()->getAcOnlineState()) {
        batteryPercentageLowAction();
    }
}

