#include "sysstate.h"
#include "utils.h"
#include "logger.h"
#include "defs.h"

#include <QFile>
#include <QTextStream>

#include <sys/statvfs.h>
#include <math.h>

SysState::SysState(QObject *parent)
    : QObject{parent}
    , m_cputemp(0)
    , m_meminfo(0)
    , m_diskinfo(0)
{
    connect(&m_detectTimer, &QTimer::timeout, this, &SysState::onDetectSysState);

    QTimer::singleShot(0, this, &SysState::onDetectSysState);
    m_detectTimer.start(10000);
}

QJsonObject SysState::sysStateInfo()
{
    QJsonObject obj;
    obj["cputemp"]= (int)floor(m_cputemp);
    obj["meminfo"]= (int)floor(m_meminfo);
    obj["diskinfo"] = (int)floor(m_diskinfo);
    return obj;
}

float SysState::cpuTemperature()
{
    QStringList cpuZones = {
        BIG_CORE0,
        BIG_CORE1,
        LITTLE_CORE
    };

    float maxTemp = 0;
    for (const QString &zone : cpuZones) {
        QFile file(zone + "/temp");
        if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
            return -1;
        QTextStream in(&file);
        in.setCodec("UTF-8");
        float temp = in.readLine().toInt() / 1000.0; // 毫摄氏度转 °C

        if (temp > maxTemp) 
            maxTemp = temp; // 也可以取平均值
    }
    return maxTemp;
}

float SysState::meminfo()
{
    FILE *fp = fopen(MEMINFO, "r");
    if (fp == NULL) {
        LOG_ERROR("get meminfo error");
        return -1;
    }

    char line[256];
    long memTotal = 0;
    long memAvailable = 0;

    while (fgets(line, sizeof(line), fp)) {
        if (sscanf(line, "MemTotal: %ld kB", &memTotal) == 1) {
            continue;
        }
        if (sscanf(line, "MemAvailable: %ld kB", &memAvailable) == 1) {
            break; // 找到 MemAvailable 后就可以退出
        }
    }

    fclose(fp);

    if (memTotal == 0) {
        LOG_ERROR("cannot read MemTotal");
        return -1;
    }

    long memUsed = memTotal - memAvailable;
    float usagePercent = 1.0 * memUsed / memTotal * 100;
    return usagePercent;
}

float SysState::diskinfo()
{
    const char *mounts[] = {MOUNT_ROOTFS, MOUNT_USERDATA};
    unsigned long long total_all = 0;
    unsigned long long free_all = 0;

    for (int i = 0; i < 2; i++) {
        struct statvfs stat;
        if (statvfs(mounts[i], &stat) != 0) {
            perror(mounts[i]);
            continue;
        }

        unsigned long long total = (unsigned long long)stat.f_blocks * stat.f_frsize;
        unsigned long long free = (unsigned long long)stat.f_bfree * stat.f_frsize;

        total_all += total;
        free_all += free;
    }

    unsigned long long used_all = total_all - free_all;
    float usagePercent = (total_all == 0) ? 0.0 : 1.0 * used_all / total_all * 100;
    return usagePercent;
}

void SysState::onDetectSysState()
{
    float cputemp  = cpuTemperature();
    float sysmeminfo = meminfo();
    float sysdiskinfo = diskinfo();

    m_cputemp = (int)floor(cputemp);
    m_meminfo = (int)floor(sysmeminfo);
    m_diskinfo = (int)floor(sysdiskinfo);
}
