/*
 * Copyright 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/>.
 */

/*
 * 读取/监听配置文件，管理应用管理的管控策略，单例类
*/
#ifndef POLICY_H
#define POLICY_H

#include <QObject>
#include <QJsonObject>
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
#include <QMap>
#endif

#define CGROUP_FREEZE "cgroup.freeze"
#define CPU_WEIGHT "cpu.weight"
#define CPU_MAX "cpu.max"
#define IO_WEIGHT "io.weight"

namespace inhibitor {
    enum Inhibitor {
        FrozenInhibitor = 1,
    };
}

class QFileSystemWatcher;
class Policy : public QObject
{
    Q_OBJECT
public:
    explicit Policy(QObject *parent = nullptr);

    enum Feature {
        CPU,
        Memory,
        IO,
        Frozen,
        MultimediaControl,
    };
    Q_ENUM(Feature)
    enum AppStatus {
        ActiveAppAdj = 0,
        ForegroundAppAdj = 100,
        BackendAppAdj = 200,
        CachedAppAdj = 300,
        SuspendedAppAdj = 400,
    };
    Q_ENUM(AppStatus)
    enum ResourceUrgency {
        Low,
        Medium,
        High,
    };
    Q_ENUM(ResourceUrgency)

    static bool isWaylandPlatform();

    /**
     * @brief features 获取当前支持的特性
     * @return 返回做支持的Feature（特性）
     */
    QList<Feature> features();

    /**
     * @brief featureEnabled 判断是否支持Feature类型
     * @param tablet 是否为平板模式
     * @param feat 判断是否支持指定的Feature类型
     * @return 支持该controller返回true，否则返回false
     */
    bool featureEnabled(bool tablet, Feature feat);

    /**
     * @brief statusSwitchInterval 获取进程状态切换时间间隔
     * @return 时间间隔
     */
    int statusSwitchInterval() const;

    AppStatus appStatus(bool appAvtived, bool appMinimized = false);

    /**
     * @brief nextAppStatus 进程切换至下一次的状态
     * @param tablet 是否为平板模式
     * @param currentStatus 当前的进程状态
     * @return 下次切换的进程状态
     */
    AppStatus nextAppStatus(AppStatus currentStatus);

    /**
     * @brief frozenStatus 获取需要对进程进行冻结的状态
     * @return
     */
    AppStatus frozenStatus() const;
    
    /**
     * @brief lastStatus 返回非睡眠状态的最后一个状态
     * @return
     */
    AppStatus lastStatus() const;

    /**
     * @brief suspendStatus 返回休眠状态
     * @return
     */
    AppStatus suspendStatus() const;

    // <appstatus, >
    QList<QMap<QString, int>> actions(Feature feat, ResourceUrgency urgency);

    int defaultCGroupVale(const QString &name);

private Q_SLOTS:
    /**
     * @brief readConf 读取配置文件
     */
    void readConf();

private:
    typedef QMap<QString, int> StatNameValue;
    typedef QMap<ResourceUrgency, StatNameValue> CGroupUrgencyStatValue;
    // <Feature, <ResourceUrgency, <statName, value>>>
    QMap<Feature, CGroupUrgencyStatValue> m_actions;
    int m_statusSwitchInterval; // s
    QFileSystemWatcher *m_confFileWatcher;
    const char *kConfFilename = "/etc/kylin-app-manager/kylin-app-manager.json";
};

#endif // POLICY_H
