package cn.reghao.bnt.common.machine;

import cn.reghao.bnt.common.machine.model.MemoryInfo;
import cn.reghao.bnt.common.machine.model.MemoryStat;
import cn.reghao.jutil.jdk.converter.ByteConverter;
import cn.reghao.jutil.jdk.machine.data.MachineData;
import cn.reghao.jutil.jdk.machine.data.detail.MemoryDetail;
import cn.reghao.jutil.jdk.math.Calculator;
import oshi.SystemInfo;
import oshi.hardware.GlobalMemory;
import oshi.hardware.VirtualMemory;

/**
 * @author reghao
 * @date 2019-10-25 13:21:25
 */
public class Memory implements MachineData<MemoryDetail, MemoryStat> {
    private final GlobalMemory globalMemory;
    private final VirtualMemory virtualMemory;
    private MemoryDetail memoryDetail;
    private ByteConverter byteConverter;

    public Memory(SystemInfo si, ByteConverter byteConverter) {
        GlobalMemory globalMemory = si.getHardware().getMemory();
        this.globalMemory = globalMemory;
        this.virtualMemory = globalMemory.getVirtualMemory();
        this.byteConverter = byteConverter;
    }

    @Override
    public MemoryDetail detail() {
        long total = globalMemory.getTotal();
        long avail = globalMemory.getAvailable();
        long swapTotal = virtualMemory.getSwapTotal();
        long swapUsed = virtualMemory.getSwapUsed();

        if (memoryDetail == null) {
            memoryDetail = new MemoryDetail(total, avail, total-avail, swapTotal, swapTotal-swapUsed);
        }

        return memoryDetail;
    }

    @Override
    public MemoryStat stat() {
        if (memoryDetail == null) {
            memoryDetail = detail();
        }

        long total = globalMemory.getTotal();
        long avail = globalMemory.getAvailable();
        memoryDetail.setAvail(avail);
        memoryDetail.setUsed(total-avail);

        long swapTotal = virtualMemory.getSwapTotal();
        long swapUsed = virtualMemory.getSwapUsed();
        memoryDetail.setAvail(swapTotal-swapUsed);
        return null;
    }

    public MemoryInfo getMemoryInfo() {
        long total = globalMemory.getTotal();
        String totalStr = byteConverter.convert(total);
        long avail = globalMemory.getAvailable();
        String availStr = byteConverter.convert(avail);
        double availPercent = Calculator.divide(avail, total)*100;

        long swapTotal = virtualMemory.getSwapTotal();
        String swapTotalStr = byteConverter.convert(swapTotal);
        long swapAvail = swapTotal - virtualMemory.getSwapUsed();
        String swapAvailStr = byteConverter.convert(swapAvail);
        double swapPercent = Calculator.divide(swapAvail, swapTotal)*100;
        return new MemoryInfo(total, totalStr, avail, availStr, availPercent,
                swapTotal, swapTotalStr, swapAvail, swapAvailStr, swapPercent);
    }
}
