// +build solaris,cgo

package system

import (
	"fmt"
	"unsafe"
)

// #cgo CFLAGS: -std=c99
// #cgo LDFLAGS: -lkstat
// #include <unistd.h>
// #include <stdlib.h>
// #include <stdio.h>
// #include <kstat.h>
// #include <sys/swap.h>
// #include <sys/param.h>
// struct swaptable *allocSwaptable(int num) {
//	struct swaptable *st;
//	struct swapent *swapent;
// 	st = (struct swaptable *)malloc(num * sizeof(swapent_t) + sizeof (int));
//	swapent = st->swt_ent;
//	for (int i = 0; i < num; i++,swapent++) {
//		swapent->ste_path = (char *)malloc(MAXPATHLEN * sizeof (char));
//	}
//	st->swt_n = num;
//	return st;
//}
// void freeSwaptable (struct swaptable *st) {
//	struct swapent *swapent = st->swt_ent;
//	for (int i = 0; i < st->swt_n; i++,swapent++) {
//		free(swapent->ste_path);
//	}
//	free(st);
// }
// swapent_t getSwapEnt(swapent_t *ent, int i) {
//	return ent[i];
// }
// int64_t getPpKernel() {
//	int64_t pp_kernel = 0;
//	kstat_ctl_t *ksc;
//	kstat_t *ks;
//	kstat_named_t *knp;
//	kid_t kid;
//
//	if ((ksc = kstat_open()) == NULL) {
//		return -1;
//	}
//	if ((ks = kstat_lookup(ksc, "unix", 0, "system_pages")) == NULL) {
//		return -1;
//	}
//	if (((kid = kstat_read(ksc, ks, NULL)) == -1) ||
//	    ((knp = kstat_data_lookup(ks, "pp_kernel")) == NULL)) {
//		return -1;
//	}
//	switch (knp->data_type) {
//	case KSTAT_DATA_UINT64:
//		pp_kernel = knp->value.ui64;
//		break;
//	case KSTAT_DATA_UINT32:
//		pp_kernel = knp->value.ui32;
//		break;
//	}
//	pp_kernel *= sysconf(_SC_PAGESIZE);
//	return (pp_kernel > 0 ? pp_kernel : -1);
// }
import "C"

// Get the system memory info using sysconf same as prtconf
func getTotalMem() int64 {
	pagesize := C.sysconf(C._SC_PAGESIZE)
	npages := C.sysconf(C._SC_PHYS_PAGES)
	return int64(pagesize * npages)
}

func getFreeMem() int64 {
	pagesize := C.sysconf(C._SC_PAGESIZE)
	npages := C.sysconf(C._SC_AVPHYS_PAGES)
	return int64(pagesize * npages)
}

// ReadMemInfo retrieves memory statistics of the host system and returns a
//  MemInfo type.
func ReadMemInfo() (*MemInfo, error) {

	ppKernel := C.getPpKernel()
	MemTotal := getTotalMem()
	MemFree := getFreeMem()
	SwapTotal, SwapFree, err := getSysSwap()

	if ppKernel < 0 || MemTotal < 0 || MemFree < 0 || SwapTotal < 0 ||
		SwapFree < 0 {
		return nil, fmt.Errorf("error getting system memory info %v\n", err)
	}

	meminfo := &MemInfo{}
	// Total memory is total physical memory less than memory locked by kernel
	meminfo.MemTotal = MemTotal - int64(ppKernel)
	meminfo.MemFree = MemFree
	meminfo.SwapTotal = SwapTotal
	meminfo.SwapFree = SwapFree

	return meminfo, nil
}

func getSysSwap() (int64, int64, error) {
	var tSwap int64
	var fSwap int64
	var diskblksPerPage int64
	num, err := C.swapctl(C.SC_GETNSWP, nil)
	if err != nil {
		return -1, -1, err
	}
	st := C.allocSwaptable(num)
	_, err = C.swapctl(C.SC_LIST, unsafe.Pointer(st))
	if err != nil {
		C.freeSwaptable(st)
		return -1, -1, err
	}

	diskblksPerPage = int64(C.sysconf(C._SC_PAGESIZE) >> C.DEV_BSHIFT)
	for i := 0; i < int(num); i++ {
		swapent := C.getSwapEnt(&st.swt_ent[0], C.int(i))
		tSwap += int64(swapent.ste_pages) * diskblksPerPage
		fSwap += int64(swapent.ste_free) * diskblksPerPage
	}
	C.freeSwaptable(st)
	return tSwap, fSwap, nil
}
