package stats

import (
	"unsafe"
)

var (
	procGetSystemTimes = kernel32.NewProc("GetSystemTimes")
)

type filetime struct {
	LowDateTime  uint32
	HighDateTime uint32
}

func filetimeToUint64(ft filetime) uint64 {
	return (uint64(ft.HighDateTime) << 32) | uint64(ft.LowDateTime)
}

func cpuBusyPercentFromDeltas(idleDelta, totalDelta float64) float64 {
	if totalDelta <= 0 {
		return 0
	}
	busyPct := (1.0 - idleDelta/totalDelta) * 100
	if busyPct < 0 {
		return 0
	}
	if busyPct > 100 {
		return 100
	}
	return busyPct
}

func (r *Reporter) SystemCPUPercent() float64 {
	r.mu.Lock()
	defer r.mu.Unlock()

	var idle, kernel, user filetime
	ret, _, _ := procGetSystemTimes.Call(
		uintptr(unsafe.Pointer(&idle)),
		uintptr(unsafe.Pointer(&kernel)),
		uintptr(unsafe.Pointer(&user)),
	)
	if ret == 0 {
		return 0
	}

	idleTicks := filetimeToUint64(idle)
	kernelTicks := filetimeToUint64(kernel)
	userTicks := filetimeToUint64(user)

	if !r.hasSample {
		r.lastIdle = idleTicks
		r.lastKernel = kernelTicks
		r.lastUser = userTicks
		r.hasSample = true
		return 0
	}

	idleDelta := float64(idleTicks - r.lastIdle)
	totalDelta := float64((kernelTicks - r.lastKernel) + (userTicks - r.lastUser))
	r.lastIdle = idleTicks
	r.lastKernel = kernelTicks
	r.lastUser = userTicks

	return cpuBusyPercentFromDeltas(idleDelta, totalDelta)
}
