package status

import (
	"fmt"
	"github.com/shirou/gopsutil/v3/disk"
	"regexp"
	"time"
)

type DiskStatus struct {
	DiskInfo
}

type DiskInfo struct {
	Device      string  `json:"device"`
	Mountpoint  string  `json:"mountpoint"`
	Fstype      string  `json:"fstype"`
	Total       uint64  `json:"total"`
	Free        uint64  `json:"free"`
	Used        uint64  `json:"used"`
	UsedPercent float64 `json:"usedPercent"`
}

func GetDiskStatus() *DiskStatus {

	ds := &DiskStatus{}

	// Get disk usage
	du, _ := disk.Usage("/")
	ds.Total = du.Total
	ds.Used = du.Used

	// 2023年7月14日 去除此部分 没什么用
	// Get logical disk info for Linux systems
	//if runtime.GOOS == "linux" {
	//	ld, _ := disk.Partitions(true)
	//	ds.LogicalDisk = ld
	//}

	return ds
}

func GetDiskInfo() ([]DiskInfo, error) {

	partitionStats, err := disk.Partitions(false)
	if err != nil {
		log.ErrorF("[GetDiskInfo] - get disk partition info error ! => %v", err)
		return nil, err
	}

	var result []DiskInfo

	for _, partitionStat := range partitionStats {
		if !MatchNeededDisk(partitionStat.Device) {
			continue
		}

		usageStat, err := disk.Usage(partitionStat.Mountpoint)
		if err != nil {
			log.ErrorF("[GetDiskInfo] - device [%s] get mount point [%s] usage error => %v", partitionStat.Device, partitionStat.Mountpoint, err)
			return nil, err
		}

		// new disk info
		diskInfo := DiskInfo{
			Device:      partitionStat.Device,
			Mountpoint:  partitionStat.Mountpoint,
			Fstype:      partitionStat.Fstype,
			Total:       usageStat.Total,
			Free:        usageStat.Free,
			Used:        usageStat.Used,
			UsedPercent: usageStat.UsedPercent,
		}

		// assign
		result = append(result, diskInfo)
	}

	return result, nil
}

func CalculateDiskIO() {

	// Get initial disk IO counters
	counters1, _ := disk.IOCounters()
	time.Sleep(time.Second)
	// Get disk IO counters after 1 second
	counters2, _ := disk.IOCounters()

	for device, counter1 := range counters1 {
		counter2 := counters2[device]
		readSpeed := float64(counter2.ReadBytes-counter1.ReadBytes) / 1024
		writeSpeed := float64(counter2.WriteBytes-counter1.WriteBytes) / 1024
		fmt.Printf("%v: read %vKB/s, write %vKB/s\n", device, readSpeed, writeSpeed)
	}
}

func MatchNeededDisk(deviceName string) bool {
	match, _ := regexp.MatchString(`^(/dev/loop)\d+`, deviceName)
	if match {
		return false
	}
	//if strings.HasPrefix(deviceName, "/sys") {
	//	return false
	//}
	//if strings.HasPrefix(deviceName, "/run") {
	//	return false
	//}
	//if strings.HasPrefix(deviceName, "/snap") {
	//	return false
	//}
	//if strings.HasPrefix(deviceName, "tracefs") {
	//	return false
	//}

	return true
}
