/*
 * Copyright 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 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 <http://www.gnu.org/licenses/>.
 */

#include "hardwarepowercontrol.h"

#include "../upmcommonfile.h"
#include "../upmcustomhardwareconfig.h"
#include <QDebug>

enum system_policy
{
    system_policy_performance = 0,
    system_policy_balance,
    system_policy_powersave,
    system_policy_max
};

HardwarePowerControl::HardwarePowerControl(QObject *parent) : QObject(parent)
{
    initGpuFrequencyState();

    initGpuFrequencyLevel();

    initIntelAudioMode();
}

HardwarePowerControl::~HardwarePowerControl() {}

void HardwarePowerControl::initGpuFrequencyState()
{
    QString config;
    if (true == UpmCustomHardwareConfig::self()->getExtendConfig(
                UPM_KEY_EXTEND_GPU_FREQUENCY_STATE, config)) {
        QStringList gpuPowerDpmState = config.split("-");
        if (system_policy_max == gpuPowerDpmState.size()) {
            m_gpuPowerDpmState[system_policy_performance] = gpuPowerDpmState[system_policy_performance];
            m_gpuPowerDpmState[system_policy_balance] = gpuPowerDpmState[system_policy_balance];
            m_gpuPowerDpmState[system_policy_powersave] = gpuPowerDpmState[system_policy_powersave];
        }
    }
}

void HardwarePowerControl::initGpuFrequencyLevel()
{
    QString config;
    if (true == UpmCustomHardwareConfig::self()->getExtendConfig(
                UPM_KEY_EXTEND_GPU_FREQUENCY_LEVEL, config)) {
        QStringList gpuPowerDpmLevel = config.split("-");
        if (system_policy_max == gpuPowerDpmLevel.size()) {
            m_gpuPowerDpmLevel[system_policy_performance] = gpuPowerDpmLevel[system_policy_performance];
            m_gpuPowerDpmLevel[system_policy_balance] = gpuPowerDpmLevel[system_policy_balance];
            m_gpuPowerDpmLevel[system_policy_powersave] = gpuPowerDpmLevel[system_policy_powersave];
        }
    }
}

void HardwarePowerControl::initIntelAudioMode()
{
    QString config;
    if (true == UpmCustomHardwareConfig::self()->getExtendConfig(
                UPM_KEY_EXTEND_INTEL_AUDIO_MODE, config)) {
        QStringList intelAudioMode = config.split("-");
        if (system_policy_max == intelAudioMode.size()) {
            m_intelAudioMode[system_policy_performance] = intelAudioMode[system_policy_performance];
            m_intelAudioMode[system_policy_balance] = intelAudioMode[system_policy_balance];
            m_intelAudioMode[system_policy_powersave] = intelAudioMode[system_policy_powersave];
        }
    }
}

void HardwarePowerControl::setGpuFrequencyMode(const int policy)
{
    if (policy < system_policy_performance || policy > system_policy_powersave) {
        return ;
    }

    QDir devfreqDir(GPU_DEVICE_BASE_PATH);
    if (devfreqDir.exists()) {
        QStringList subDirs = devfreqDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);

        foreach (const QString &subDirName, subDirs) {
            QString subDirPath = devfreqDir.filePath(subDirName) + "/";
            if (UpmCommonFile::exists(subDirPath, GPU_POWER_GOVERNOR)) {
                UpmCommonFile::write(subDirPath, GPU_POWER_GOVERNOR, m_gpuPowerGovernor[policy]);
            }
        }
    }

    if (true == UpmCommonFile::exists(GPU_DEVICES_PATH, GPU_POWER_DPM_STATE)) {
        UpmCommonFile::write(GPU_DEVICES_PATH, GPU_POWER_DPM_STATE, m_gpuPowerDpmState[policy]);
    }
    if (true == UpmCommonFile::exists(GPU_DEVICES_PATH, GPU_POWER_DPM_LEVEL)) {
        UpmCommonFile::write(GPU_DEVICES_PATH, GPU_POWER_DPM_LEVEL, m_gpuPowerDpmLevel[policy]);
    }
}

void HardwarePowerControl::setAudioMode(const int policy)
{
    if (policy < system_policy_performance || policy > system_policy_powersave) {
        return ;
    }

    UpmCommonFile::write(INTEL_AUDIO_PATH, INTEL_AUDIO_FILE, m_intelAudioMode[policy]);
}

void HardwarePowerControl::setPcieAspmMode(const int policy)
{
    QStringList pcieAspmMode;

    if(true == UpmCustomHardwareConfig::self()->isHygonCpu()) {
         pcieAspmMode = QStringList{"performance", "default","powersave"};
    } else if(true == UpmCustomHardwareConfig::self()->isZhaoxinCpu()) {
         pcieAspmMode = QStringList{"performance", "default", "default"};
    } else {
         pcieAspmMode = QStringList{"default", "powersave", "powersave"};
    }

    if (policy < system_policy_performance || policy > system_policy_powersave) {
        return ;
    }

    UpmCommonFile::write(PCIE_ASPM_PATH, PCIE_ASPM_FILE, pcieAspmMode[policy]);
}
