package bytes

import (
	"agent/commons/debug"
	"agent/commons/types"
	"agent/commons/utils"
	"agent/defines/derrs"
	crand "crypto/rand"
)

func Width[T types.Integer](val T) int {
	if val == 0 {
		return 0
	}
	v := uint64(val)
	for n := 1; n <= 8; n++ {
		if v <= (1<<(8*n))-1 {
			return n
		}
	}
	return 8
}

func Range[T types.Integer](val T, from int, width int) T {
	return (val >> from) & (1<<width - 1)
}

func Set[T types.Integer](data []byte, offset int, value T, width int) int {
	if width > 8 {
		debug.Panic(derrs.NewIncorrectParamsError("width cannot be greater than 8"))
	}
	v := uint64(value)
	for i := 0; i < width; i++ {
		data[offset+i] = uint8(v >> (8 * i))
	}
	return offset + width
}

func ToNum[T types.Integer](data []byte, width int) (res T, ok bool) {
	if (int64(len(data)) < int64(width)) || width > 8 {
		return res, false
	}
	var val uint64
	for i, bt := range data[:int64(width)] {
		val |= uint64(bt) << (i * 8)
	}
	return T(val), true
}

func Random(size int) (res []byte) {
	if size == 0 {
		return nil
	}
	res = make([]byte, size)
	n, _ := crand.Read(res)
	return res[:n]
}

func Random2(min int, max ...int) (res []byte) {
	max_ := 0
	if len(max) > 0 && max[0] > 0 {
		max_ = max[0]
	}
	if min == 0 && max_ == 0 {
		return nil
	}
	size := min
	if max_-min > 0 {
		size = utils.IntN(max_-size) + size
	}
	res = make([]byte, size)
	n, _ := crand.Read(res)
	return res[:n]
}
