package metrics

import (
	"log"
	"strconv"

	"github.com/prometheus/client_golang/prometheus"
	"libvirt.org/go/libvirt"
)

var (
	// Compute
	libvirtNodeCPUUsage = prometheus.NewDesc(
		prometheus.BuildFQName("libvirt", "node", "cpu_time_seconds_total"),
		"CPU usage of node",
		[]string{"cluster", "node", "thread"},
		nil)

	libvirtNodeMemoryUsageBytes = prometheus.NewDesc(
		prometheus.BuildFQName("libvirt", "node", "memory_usage_bytes"),
		"Memory usage of the node, in bytes.",
		[]string{"cluster", "node", "total"},
		nil)
)

func CollectNode(conn *libvirt.Connect, ch chan<- prometheus.Metric, hostname string) error {
	config, err := Config()
	if err != nil {
		log.Fatalf("Fail to read file: %v", err)
	}

	// Node
	node_info, err := conn.GetNodeInfo()
	if err != nil {
		return err
	}

	nodeCPU, _ := conn.GetCPUStats(int(libvirt.NODE_CPU_STATS_ALL_CPUS), 0) // rate(libvirt_node_cpu_time_seconds_total[10s]) * 100
	nodeMemory, _ := conn.GetMemoryStats(libvirt.NODE_MEMORY_STATS_ALL_CELLS, 0)

	ch <- prometheus.MustNewConstMetric(
		libvirtNodeCPUUsage,
		prometheus.CounterValue,
		float64(nodeCPU.Kernel+nodeCPU.User+nodeCPU.Iowait)/1e9, // From nsec to sec
		config.Section("").Key("id").String(),
		hostname,
		strconv.FormatInt(int64(node_info.Sockets*node_info.Cores*node_info.Threads), 10),
	)

	ch <- prometheus.MustNewConstMetric(
		libvirtNodeMemoryUsageBytes,
		prometheus.GaugeValue,
		float64(nodeMemory.Total-(nodeMemory.Buffers+nodeMemory.Free+nodeMemory.Cached))*1024,
		config.Section("").Key("id").String(),
		hostname,
		strconv.FormatInt(int64(nodeMemory.Total), 10),
	)

	return nil
}

func (e *LibvirtExporter) DescribeNode(ch chan<- *prometheus.Desc) {
	ch <- libvirtNodeCPUUsage
	ch <- libvirtNodeMemoryUsageBytes
}