package se.christianjensen.maintenance.sigar;

import org.hyperic.sigar.CpuPerc;
import org.hyperic.sigar.Sigar;
import org.hyperic.sigar.SigarException;
import se.christianjensen.maintenance.representation.cpu.Cpu;
import se.christianjensen.maintenance.representation.cpu.CpuInfo;
import se.christianjensen.maintenance.representation.cpu.CpuTime;

import java.util.ArrayList;
import java.util.List;

public class CpuMetrics extends AbstractSigarMetric {
    private static final long HACK_DELAY_MILLIS = 500;

    private final CpuInfo info;

    protected CpuMetrics(Sigar sigar) {
        super(sigar);
        info = cpuInfo();
    }

    public Cpu getCpu() {
        return new Cpu(cpuInfo(), cpuTimeSysPercent(), totalCpuTime(), cpuTimesPerCore(cpuPercList()));
    }

    public CpuTime getCpuTimeByCoreIndex(int id) throws IllegalArgumentException {
        CpuPerc[] cpuPercs = cpuPercList();
        if (id > cpuPercs.length) {
            throw new IllegalArgumentException("No core with id " + Integer.toString(id) + " were found");
        }

        List<CpuTime> result = cpuTimesPerCore(new CpuPerc[]{cpuPercs[id]});
        return result.get(0);
    }

    protected double cpuTimeSysPercent() {
        List<CpuTime> cpus = cpuTimesPerCore(cpuPercList());
        double userTime = 0.0;
        for (CpuTime cpu : cpus) {
            userTime += cpu.sys();
        }
        return userTime / 1.0;
    }

    protected CpuTime totalCpuTime() {
        CpuPerc cpuPerc;
        try {
            cpuPerc = sigar.getCpuPerc();
            if (Double.isNaN(cpuPerc.getIdle())) {
                try {
                    Thread.sleep(HACK_DELAY_MILLIS);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    return CpuTime.fromSigarBean(cpuPerc);
                }
                cpuPerc = sigar.getCpuPerc();
            }
            return CpuTime.fromSigarBean(cpuPerc);
        } catch (SigarException e) {
            //swallow
        }
        return null;
    }

    protected List<CpuTime> cpuTimesPerCore(CpuPerc[] percList) {
        List<CpuTime> result = new ArrayList<>();
        for (CpuPerc cp : percList) {
            result.add(CpuTime.fromSigarBean(cp));
        }
        return result;
    }

    protected CpuInfo cpuInfo() {
        try {
            org.hyperic.sigar.CpuInfo[] infos = sigar.getCpuInfoList();
            if (infos == null || infos.length == 0) {
                return null;
            }
            return CpuInfo.fromSigarBean(infos[0]);
        } catch (SigarException e) {
            // give up
            return null;
        }
    }

    protected CpuPerc[] cpuPercList() {
        CpuPerc[] cpus = null;
        try {
            cpus = sigar.getCpuPercList();
            if (Double.isNaN(cpus[0].getIdle())) {
            /*
             * XXX: Hacky workaround for strange Sigar behaviour.
             * If you call sigar.getCpuPerfList() too often(?),
             * it returns a steaming pile of NaNs.
             *
             * See suspicious code here:
             * https://github.com/hyperic/sigar/blob/master/bindings/java/src/org/hyperic/sigar/Sigar.java#L345-348
             *
             */
                try {
                    Thread.sleep(HACK_DELAY_MILLIS);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    return cpus;
                }
                cpus = sigar.getCpuPercList();
                if (cpus == null) {
                    return cpus;
                }
            }
        } catch (SigarException e) {
            // give up
        }
        if (cpus == null || cpus.length == 0) {
            return null;
        }

        return cpus;
    }

}

@@ -2854,407 +2854,8 @@
 ) %7B%0A
-            /*%0A             * XXX: Hacky workaround for strange Sigar behaviour.%0A             * If you call sigar.getCpuPerfList() too often(?),%0A             * it returns a steaming pile of NaNs.%0A             *%0A             * See suspicious code here:%0A             * https://github.com/hyperic/sigar/blob/master/bindings/java/src/org/hyperic/sigar/Sigar.java#L345-348%0A             *%0A             */%0A
     

Remove comment from workaround