package backend

import (
	"fmt"
	"get-container/cmd/hytop/lib"
	"math"
	"strconv"
	"strings"
	"sync"
	"time"
)

var (
	DCUSInfoMap   *DCUInfoMap = nil // 记录dcu信息
	Rocmlib                   = lib.Rocmlib_instance
	DriverVersion             = ""
)

const (
	ENVUser = "USER"
)

// Init 初始化本包的数据
func Init() error {
	Rocmlib = lib.GetRocmlib()
	_, err := Rocmlib.Init()
	if err != nil {
		return err
	}
	DriverVersion, err = Rocmlib.GetSystemDriverVersion()
	if err != nil {
		return err
	}
	_, err = Rocmlib.GetDevNumber()
	DCUSInfoMap = &DCUInfoMap{
		info: make(map[int]*DCUInfo),
		lock: sync.RWMutex{},
	}
	return err
}

func Shutdown() {
	Rocmlib.Shutdown()
}

type DCUInfoMap struct {
	lock sync.RWMutex
	info map[int]*DCUInfo
}

type DCUInfo struct {
	lock             sync.RWMutex
	Id               int
	Name             string
	PerformanceLevel string
	Fan              string
	Temp             float32 // 单位是摄氏度
	PwrAvg           float32 // 单位是瓦
	PwrCap           float32 // 单位是瓦
	BusId            string
	MemTotal         uint64
	MemUsed          uint64
	MemUsedPerent    float32
	DCUUTil          float32
}

func (m *DCUInfoMap) UpdateInfo() error {
	num, err := Rocmlib.GetDevNumber()
	if err != nil {
		return err
	}
	names, err := Rocmlib.GetDevName()
	if err != nil {
		return err
	}
	plevel, err := Rocmlib.GetPerfLevel()
	if err != nil {
		return err
	}
	fan, err := Rocmlib.GetFanSpeed()
	if err != nil {
		return err
	}
	temp, err := Rocmlib.GetTemp()
	if err != nil {
		return err
	}
	pwrAvg, err := Rocmlib.GetPowerAvg()
	if err != nil {
		return err
	}
	pwrCap, err := Rocmlib.GetPowerCap()
	if err != nil {
		return err
	}
	busid, err := Rocmlib.GetPCIBusId()
	if err != nil {
		return err
	}
	memTotal, err := Rocmlib.GetMemTotal()
	if err != nil {
		return err
	}
	memUsed, err := Rocmlib.GetMemUsed()
	if err != nil {
		return err
	}
	dcu, err := Rocmlib.GetBusyPercent()
	if err != nil {
		return err
	}

	set := make(map[int]bool)

	m.lock.Lock()
	defer m.lock.Unlock()

	for i := range num {
		info, have := m.info[i]
		if !have {
			info = &DCUInfo{}
			m.info[i] = info
		}
		info.lock.Lock()
		info.Id = i
		info.Name = names[i]
		info.PerformanceLevel = plevel[i]
		if rpm, have := fan[i]; !have || rpm == 0 {
			info.Fan = "N/A"
		} else {
			info.Fan = strconv.Itoa(int(rpm))
		}
		info.Temp = float32(temp[i]) / 1000
		info.PwrAvg = float32(pwrAvg[i]) / 1000000
		info.PwrCap = float32(pwrCap[i]) / 1000000
		info.BusId = busid[i]
		info.MemTotal = memTotal[i]
		info.MemUsed = memUsed[i]
		if info.MemTotal == 0 {
			info.MemUsedPerent = 0
		} else {
			info.MemUsedPerent = float32(info.MemUsed) / float32(info.MemTotal) * 100
		}
		info.DCUUTil = float32(dcu[i])
		info.lock.Unlock()
		set[i] = true
	}
	for k := range m.info {
		a, b := set[k]
		if a && b {
			continue
		}
		delete(m.info, k)
	}
	return nil
}

func (m *DCUInfoMap) GetInfo() (map[int]*DCUInfo, sync.Locker) {
	rl := m.lock.RLocker()
	rl.Lock()
	return m.info, rl
}

// DurationStr 将时间段格式化为 小时:分钟:秒 的格式
func DurationStr(d time.Duration) string {
	h := int(math.Floor(d.Hours()))
	m := int(d.Minutes()) % 60
	s := int(math.Floor(d.Seconds())) % 60
	if h <= 96 {
		return strings.Replace(fmt.Sprintf("%d:%2d:%2d", h, m, s), " ", "0", -1)
	} else {
		return fmt.Sprintf("%.1f days", d.Hours()/24)
	}
}
