package GoUtil

import (
	"fmt"
	"math/rand"
	"reflect"
	"server/game/mod/item"
	"sort"
	"strconv"
	"strings"
)

func IntSlice(d interface{}) []int {
	if d == nil {
		return []int{}
	}

	// Type assertion with safety check
	result, ok := d.([]int)
	if !ok {
		return []int{}
	}
	return result
}

func IntSliceInterface(d []interface{}) []int {
	result := make([]int, 0, len(d))
	for _, v := range d {
		num := Int(v)
		result = append(result, num)
	}
	return result
}
func IntToInt32(d []int) []int32 {
	r := make([]int32, 0, len(d))
	for _, d := range d {
		r = append(r, int32(d))
	}
	return r
}

func Int32ToInt(d []int32) []int {
	r := make([]int, 0, len(d))
	for _, d := range d {
		r = append(r, int(d))
	}
	return r
}

func StringToInt(d []string) []int {
	r := make([]int, 0, len(d))
	for _, d := range d {
		n, _ := strconv.Atoi(d)
		r = append(r, n)
	}
	return r
}

func RandPopSlice(slice []int) ([]int, int) {
	slen := len(slice)
	if slen == 0 {
		return slice, -1
	}
	Id := rand.Intn(slen)
	Val := slice[Id]
	Slice2 := append(slice[0:Id], slice[Id+1:]...)
	return Slice2, Val
}

func RandSlice(slice []int) int {
	slen := len(slice)
	if slen == 0 {
		return 0
	}
	Id := rand.Intn(slen)
	return slice[Id]
}

func RandItem(slice []*item.Item) *item.Item {
	slen := len(slice)
	if slen == 0 {
		return nil
	}
	Id := rand.Intn(slen)
	return slice[Id]
}

func RandSliceNum(s []int, num int) []int {
	slice := make([]int, len(s))
	copy(slice, s)
	r := make([]int, 0, num)
	if num <= 0 || len(slice) < num {
		return slice
	}

	for i := 0; i < num; i++ {
		Id := rand.Intn(len(slice))
		r = append(r, slice[Id])
		slice = append(slice[0:Id], slice[Id+1:]...)
	}
	return r
}

func RandSliceNum2(s []interface{}, num int) []interface{} {
	slice := make([]interface{}, len(s))
	copy(slice, s)
	r := make([]interface{}, 0, num)
	if num <= 0 || len(slice) < num {
		return slice
	}

	for i := 0; i < num; i++ {
		Id := rand.Intn(len(slice))
		r = append(r, slice[Id])
		slice = append(slice[0:Id], slice[Id+1:]...)
	}
	return r
}

func RandSliceNumNonAdjacent(s []int, num int) []int {
	slice := make([]int, len(s))
	copy(slice, s)
	if len(slice) < 2*num {
		return nil
	}
	sort.Ints(slice)
	result := make([]int, 0, num)
	for len(result) < num {
		Id := rand.Intn(len(slice))
		result = append(result, slice[Id])
		slice = SubAdjacentElemSlice(slice, Id)
	}
	return result
}

func SubAdjacentElemSlice(s []int, Id int) []int {
	r := make([]int, 0, len(s))
	for k, v := range s {
		if k < Id-1 || k > Id+1 {
			r = append(r, v)
		}
	}
	return r
}

func RandStringSlice(slice []string) string {
	slen := len(slice)
	if slen == 0 {
		return ""
	}
	Id := rand.Intn(slen)
	return slice[Id]
}

func SliceStringToInt(s []string) []int {
	if len(s) == 0 {
		return []int{}
	}
	r := make([]int, 0, len(s))
	for _, v := range s {
		v = strings.Trim(v, " ")
		v1, _ := strconv.Atoi(v)
		r = append(r, v1)
	}
	return r
}

func SliceIntToInt32(s []int) []int32 {
	r := make([]int32, 0, len(s))
	for _, v := range s {
		r = append(r, int32(v))
	}
	return r
}

func PopElemSlice(s []int, Id int) ([]int, bool) {
	for k, v := range s {
		if v == Id {
			return append(s[0:k], s[k+1:]...), true
		}
	}
	return s, false
}

func PopStringElemSlice(s0 []string, Id string) ([]string, bool) {
	s := make([]string, len(s0))
	copy(s, s0)
	for k, v := range s {
		if v == Id {
			return append(s[0:k], s[k+1:]...), true
		}
	}
	return s, false
}

func ElemInSlice(s []int, Id int) bool {
	for _, v := range s {
		if v == Id {
			return true
		}
	}
	return false
}

func GetElemNum(s []int, Id int) int {
	n := 0
	for _, v := range s {
		if v == Id {
			n++
		}
	}
	return n
}

func InArray(Id int, s []int) bool {
	for _, v := range s {
		if v == Id {
			return true
		}
	}
	return false
}

func InArray64(Id int64, s []int64) bool {
	for _, v := range s {
		if v == Id {
			return true
		}
	}
	return false
}

func InStringArray(Id string, s []string) bool {
	for _, v := range s {
		if v == Id {
			return true
		}
	}
	return false
}

// toInterfaceSlice converts a slice of strings to a slice of empty interfaces
func ToInterfaceSlice(slice []string) []interface{} {
	result := make([]interface{}, len(slice))
	for i, v := range slice {
		result[i] = v
	}
	return result
}

// a - b
func SubSlices(a, b []int) []int {
	result := make([]int, 0, len(a))
	for _, num := range a {
		if !InArray(num, b) {
			result = append(result, num)
		}
	}
	return result
}

func PopSlice(s []int) (int, []int) {
	if len(s) == 0 {
		return -1, s
	}
	return s[0], s[1:]
}

// 判断两个切片的元素是否一致
func SliceEqual(a, b []int) bool {
	if len(a) != len(b) {
		return false
	}

	// 创建副本以避免修改原始切片
	aCopy := make([]int, len(a))
	bCopy := make([]int, len(b))
	copy(aCopy, a)
	copy(bCopy, b)

	// 对切片进行排序
	sort.Ints(aCopy)
	sort.Ints(bCopy)

	// 比较排序后的切片
	return reflect.DeepEqual(aCopy, bCopy)
}

func SlicesEqualString(a, b []string) bool {
	if len(a) != len(b) {
		return false
	}

	// 创建副本以避免修改原始切片
	aCopy := make([]string, len(a))
	bCopy := make([]string, len(b))
	copy(aCopy, a)
	copy(bCopy, b)

	// 对切片进行排序
	sort.Strings(aCopy)
	sort.Strings(bCopy)

	// 比较排序后的切片
	return reflect.DeepEqual(aCopy, bCopy)
}

// IsContainSlice checks if all elements of s2 are contained in s.
func IsContainSlice(s []int, s2 []int) bool {
	if len(s2) == 0 {
		return true
	}
	if len(s) < len(s2) {
		return false
	}
	for _, v := range s2 {
		if !InArray(v, s) {
			return false
		}
		s = SubSlices(s, []int{v})
	}
	return true
}

func InitNumSlice(start, end int) []int {
	result := make([]int, 0, end-start+1)
	for i := start; i <= end; i++ {
		result = append(result, i)
	}
	return result
}

func IntSliceToString(slice []int) string {
	str := fmt.Sprintf("%v", slice)
	str = strings.Trim(str, "[]")
	return str
}

func PopStringArray(s []string) (string, []string) {
	if len(s) == 0 {
		return "", s
	}
	return s[0], s[1:]
}

func ShuffleStringArray(s []string) []string {
	r := make([]string, len(s))
	perm := rand.Perm(len(s))
	for i, v := range perm {
		r[v] = s[i]
	}
	return r
}

func ShuffleArray(s []int) []int {
	r := make([]int, len(s))
	perm := rand.Perm(len(s))
	for i, v := range perm {
		r[v] = s[i]
	}
	return r
}

func IsContain(s []int, s2 []int) bool {
	for _, v := range s2 {
		if !InArray(v, s) {
			return false
		}
		s = SubSlices(s, []int{v})
	}
	return true
}

func IsSameElem(s []int) bool {
	r := make(map[int]struct{})
	for _, v := range s {
		if _, ok := r[v]; ok {
			return true
		}
		r[v] = struct{}{}
	}
	return false
}
