package backend

import (
	"fmt"
	"get-container/utils"
	"os/exec"
	"sort"
	"strconv"
	"strings"
	"time"
)

type LoginUserInfo struct {
	Name      string    `json:"name"`      // 用户名
	TTY       string    `json:"tty"`       // 占用的终端
	LoginTime time.Time `json:"loginTime"` // 登录时间
	Pid       []int32   `json:"pid"`       // 登录的接管进程
	LoginFrom string    `json:"loginFrom"` // 登录方式
}

func GetOnlineUser() ([]LoginUserInfo, error) {
	output, err := exec.Command("who", "-u", "-H").Output()
	if err != nil {
		return nil, err
	}
	return parseWhoOutput(strings.Trim(string(output), "\n"))
}

func parseWhoOutput(s string) ([]LoginUserInfo, error) {
	lines := strings.Split(s, "\n")
	if len(lines) < 1 {
		return make([]LoginUserInfo, 0), nil
	}
	result := make([]LoginUserInfo, 0, len(lines))
	for _, v := range lines[1:] {
		fs := strings.Fields(v)
		lui := LoginUserInfo{}
		lui.Name = fs[0]
		lui.TTY = fs[1]
		t, err := time.Parse("2006-01-02 15:04", fmt.Sprintf("%s %s", fs[2], fs[3]))
		if err != nil {
			t = time.Now()
		}
		lui.LoginTime = t
		pidStr := strings.Split(fs[5], ",")
		lui.Pid = make([]int32, 0, 2)
		for _, pidstr := range pidStr {
			i, err := strconv.Atoi(pidstr)
			if err != nil {
				continue
			}
			lui.Pid = append(lui.Pid, int32(i))
		}
		lui.LoginFrom = strings.Trim(strings.Trim(fs[6], "("), ")")
		result = append(result, lui)
	}
	return result, nil
}

func GetSysLoad() (*SysInfo, error) {
	s, err := utils.GetSysInfo()
	if err != nil {
		return nil, err
	}
	ss := SysInfo(*s)
	return &ss, err
}

type SysInfo utils.SysInfo

type DCULoad struct {
	Name          string  `json:"name"`
	Index         int     `json:"index"`
	Fan           string  `json:"fan"`
	Temp          float32 `json:"temp"`   // 单位是摄氏度
	PwrAvg        float32 `json:"pwrAvg"` // 单位是瓦
	PwrCap        float32 `json:"pwrCap"` // 单位是瓦
	MemTotal      uint64  `json:"memTotal"`
	MemUsed       uint64  `json:"memUsed"`
	MemUsedPerent float32 `json:"memUsedPercent"`
	DCUUTil       float32 `json:"dcuUtilPercent"`
}

func GetDCULoad() ([]DCULoad, error) {
	if DCUSInfoMap == nil {
		err := Init()
		if err != nil {
			return nil, err
		}
	}
	if err := DCUSInfoMap.UpdateInfo(); err != nil {
		return nil, err
	}
	info, lock := DCUSInfoMap.GetInfo()
	result := make([]DCULoad, 0, len(info))
	for _, v := range info {
		l := DCULoad{
			Name:          v.Name,
			Index:         v.Id,
			Fan:           v.Fan,
			Temp:          v.Temp,
			PwrAvg:        v.PwrAvg,
			PwrCap:        v.PwrCap,
			MemTotal:      v.MemTotal,
			MemUsed:       v.MemUsed,
			MemUsedPerent: v.MemUsedPerent,
			DCUUTil:       v.DCUUTil,
		}
		result = append(result, l)
	}
	lock.Unlock()
	sort.Slice(result, func(i, j int) bool {
		return result[i].Index < result[j].Index
	})
	return result, nil
}

type AllInfo struct {
	DCUInfo        []DCULoad       `json:"dcuInfo"`
	SysInfo        SysInfo         `json:"sysInfo"`
	OnlineUserInfo []LoginUserInfo `json:"loginUserInfo"`
}
