// Copyright (c) 2024-2026 Celestino Amoroso (celestino.amoroso@gmail.com).
// All rights reserved.

// utils.go
package util

import (
	"reflect"

	"git.portale-stac.it/go-pkg/expr/types"
	"git.portale-stac.it/go-pkg/expr/types/array"
	"git.portale-stac.it/go-pkg/expr/types/dict"
	"git.portale-stac.it/go-pkg/expr/types/float"
)

func IsFunc(v any) bool {
	return reflect.TypeOf(v).Kind() == reflect.Func
}

func FromGenericAny(v any) (exprAny any, ok bool) {
	if v != nil {
		if exprAny, ok = v.(bool); ok {
			return
		}
		if exprAny, ok = v.(string); ok {
			return
		}
		if exprAny, ok = types.AnyInteger(v); ok {
			return
		}
		if exprAny, ok = float.AnyFloat(v); ok {
			return
		}
		if exprAny, ok = v.(*dict.DictType); ok {
			return
		}
		if exprAny, ok = v.(*array.ArrayType); ok {
			return
		}
	}
	return
}

func CopyMap[K comparable, V any](dest, source map[K]V) map[K]V {
	for k, v := range source {
		dest[k] = v
	}
	return dest
}

// func CloneMap[K comparable, V any](source map[K]V) map[K]V {
// 	dest := make(map[K]V, len(source))
// 	return CopyMap(dest, source)
// }

func CopyFilteredMap[K comparable, V any](dest, source map[K]V, filter func(key K) (accept bool)) map[K]V {
	// fmt.Printf("--- Clone with filter %p\n", filter)
	if filter == nil {
		return CopyMap(dest, source)
	} else {
		for k, v := range source {
			if filter(k) {
				// fmt.Printf("\tClone var %q\n", k)
				dest[k] = v
			}
		}
	}
	return dest
}

func CloneFilteredMap[K comparable, V any](source map[K]V, filter func(key K) (accept bool)) map[K]V {
	dest := make(map[K]V, len(source))
	return CopyFilteredMap(dest, source, filter)
}

func ForAll[T, V any](ts []T, fn func(T) V) []V {
	result := make([]V, len(ts))
	for i, t := range ts {
		result[i] = fn(t)
	}
	return result
}

func UnquoteString(src string) string {
	if len(src) > 1 && src[0] == '"' && src[len(src)-1] == '"' {
		src = src[1 : len(src)-1]
	}
	return src
}
