package langext

type MapEntry[T comparable, V any] struct {
	Key   T
	Value V
}

func MapKeyArr[T comparable, V any](v map[T]V) []T {
	result := make([]T, 0, len(v))
	for k := range v {
		result = append(result, k)
	}
	return result
}

func MapValueArr[T comparable, V any](v map[T]V) []V {
	result := make([]V, 0, len(v))
	for _, mv := range v {
		result = append(result, mv)
	}
	return result
}

func ArrToMap[T comparable, V any](a []V, keyfunc func(V) T) map[T]V {
	result := make(map[T]V, len(a))
	for _, v := range a {
		result[keyfunc(v)] = v
	}
	return result
}

func ArrToKVMap[T any, K comparable, V any](a []T, keyfunc func(T) K, valfunc func(T) V) map[K]V {
	result := make(map[K]V, len(a))
	for _, v := range a {
		result[keyfunc(v)] = valfunc(v)
	}
	return result
}

func ArrToSet[T comparable](a []T) map[T]bool {
	result := make(map[T]bool, len(a))
	for _, v := range a {
		result[v] = true
	}
	return result
}

func MapToArr[T comparable, V any](v map[T]V) []MapEntry[T, V] {
	result := make([]MapEntry[T, V], 0, len(v))
	for mk, mv := range v {
		result = append(result, MapEntry[T, V]{
			Key:   mk,
			Value: mv,
		})
	}
	return result
}

func CopyMap[K comparable, V any](a map[K]V) map[K]V {
	result := make(map[K]V, len(a))
	for k, v := range a {
		result[k] = v
	}
	return result
}

func ForceMap[K comparable, V any](v map[K]V) map[K]V {
	if v == nil {
		return make(map[K]V)
	} else {
		return v
	}
}

func MapMerge[K comparable, V any](base map[K]V, arr ...map[K]V) map[K]V {
	res := make(map[K]V, len(base)*(1+len(arr)))

	for k, v := range base {
		res[k] = v
	}

	for _, m := range arr {
		for k, v := range m {
			res[k] = v
		}
	}

	return res
}