package utils

import (
	"fmt"
	"mongo.games.com/goserver/core/logger"
	"runtime"
	"time"
)

func Avg(items []time.Duration) time.Duration {
	var sum time.Duration
	for _, item := range items {
		sum += item
	}
	return time.Duration(int64(sum) / int64(len(items)))
}

// human readable format
func ToH(bytes uint64) string {
	switch {
	case bytes < 1024:
		return fmt.Sprintf("%dB", bytes)
	case bytes < 1024*1024:
		return fmt.Sprintf("%.2fK", float64(bytes)/1024)
	case bytes < 1024*1024*1024:
		return fmt.Sprintf("%.2fM", float64(bytes)/1024/1024)
	default:
		return fmt.Sprintf("%.2fG", float64(bytes)/1024/1024/1024)
	}
}

// short string format
func ToS(d time.Duration) string {

	u := uint64(d)
	if u < uint64(time.Second) {
		switch {
		case u == 0:
			return "0"
		case u < uint64(time.Microsecond):
			return fmt.Sprintf("%.2fns", float64(u))
		case u < uint64(time.Millisecond):
			return fmt.Sprintf("%.2fus", float64(u)/1000)
		default:
			return fmt.Sprintf("%.2fms", float64(u)/1000/1000)
		}
	} else {
		switch {
		case u < uint64(time.Minute):
			return fmt.Sprintf("%.2fs", float64(u)/1000/1000/1000)
		case u < uint64(time.Hour):
			return fmt.Sprintf("%.2fm", float64(u)/1000/1000/1000/60)
		default:
			return fmt.Sprintf("%.2fh", float64(u)/1000/1000/1000/60/60)
		}
	}

}

func CatchPanic(f func()) (err interface{}) {
	defer func() {
		err = recover()
		if err != nil {
			logger.Logger.Warnf("%s panic: %s", f, err)
			var buf [4096]byte
			n := runtime.Stack(buf[:], false)
			logger.Logger.Error("stack--->", string(buf[:n]))
		}
	}()
	f()
	return
}

func RunPanicless(f func()) (panicless bool) {
	defer func() {
		err := recover()
		panicless = err == nil
		if err != nil {
			logger.Logger.Warnf("%s panic: %s", f, err)
			var buf [4096]byte
			n := runtime.Stack(buf[:], false)
			logger.Logger.Error("stack--->", string(buf[:n]))
		}
	}()

	f()
	return
}

func RepeatUntilPanicless(f func()) {
	for !RunPanicless(f) {
	}
}
