package utils

import (
	
	
	
	
	
	
	
	
	

	
	am 
)

// EnvAmHostname will override the hostname in all machine names.
const EnvAmHostname = "AM_HOSTNAME"

// J joins state names into a single string
func ( []string) string {
	return strings.Join(, " ")
}

// Jw joins state names into a single string with a separator.
func ( []string,  string) string {
	return strings.Join(, )
}

func () string {
	,  := debug.ReadBuildInfo()
	if ! {
		return "(devel)"
	}

	 := .Main.Version
	if  == "" {
		return "(devel)"
	}

	return 
}

// TODO remove if that speeds things up
func [ any]( chan ) {
	select {
	case <-:
	default:
		close()
	}
}

func [ ~[],  comparable]( ,  )  {
	 := slices.Index(, )
	 := slices.Clone()
	if  == -1 {
		return 
	}
	return slices.Delete(, , +1)
}

// SlicesNone returns true if none of the elements of coll2 are in coll1.
func [ ~[],  ~[],  comparable]( ,  ) bool {
	for ,  := range  {
		if slices.Contains(, ) {
			return false
		}
	}
	return true
}

// SlicesEvery returns true if all elements of coll2 are in coll1.
func [ ~[],  ~[],  comparable]( ,  ) bool {
	for ,  := range  {
		if !slices.Contains(, ) {
			return false
		}
	}
	return true
}

func [ ~[],  comparable]( )  {
	var  
	for ,  := range  {
		if !slices.Contains(, ) {
			 = append(, )
		}
	}
	return 
}

// RandId generates a random ID of the given length (defaults to 8).
func ( int) string {
	if  == 0 {
		 = 16
	}
	++
	 =  / 2

	 := make([]byte, )
	,  := rand.Read()
	if  != nil {
		return "error"
	}

	return hex.EncodeToString()
}

func () string {
	if  := os.Getenv(EnvAmHostname);  != "" {
		return 
	}
	,  := os.Hostname()
	if  == "" {
		 = "localhost"
	}

	return 
}

func ( string,  ...any) string {
	return fmt.Sprintf(dedent.Dedent(strings.Trim(, "\n")), ...)
}

func ( string,  ...any) {
	fmt.Printf(dedent.Dedent(strings.Trim(, "\n")), ...)
}

// TruncateStr with shorten the string and leave a tripedot suffix.
func ( string,  int) string {
	if len() <=  {
		return 
	}
	if  < 5 {
		return [:]
	} else {
		return [:-3] + "..."
	}
}

func ( string,  int,  string) string {
	for {
		 += 
		if len() >  {
			return [0:]
		}
	}
}

func () string {
	 := make([]byte, 4024)
	 := runtime.Stack(, false)
	 := string([:])
	 := strings.Split(, "\n")
	 := strings.Contains(, "panic")
	slices.Reverse()

	 := []string{
		"AddErr", "AddErrState", "Remove", "Remove1", "Add", "Add1", "Set",
	}
	// TODO trim tails start at reflect.Value.Call({
	//  with asyncmachine 2 frames down

	// trim the head, remove junk
	 := false
	for ,  := range  {
		if  && strings.HasPrefix(, "panic(") {
			 = [:-1]
			break
		}

		for ,  := range  {
			if strings.Contains("machine.(*Machine)."++"(", ) {
				 = [:-1]
				 = true
				break
			}
		}
		if  {
			break
		}
	}
	slices.Reverse()
	 := strings.Join(, "\n")

	if  := os.Getenv(am.EnvAmTraceFilter);  != "" {
		 = strings.ReplaceAll(, , "")
	}

	return 
}

func () (string, error) {
	,  := net.InterfaceAddrs()
	if  != nil {
		return "", 
	}

	for ,  := range  {
		if ,  := .(*net.IPNet);  && !.IP.IsLoopback() {
			if .IP.To4() != nil && .IP.IsGlobalUnicast() {
				return .IP.String(), nil
			}
		}
	}

	return "", fmt.Errorf("no global unicast IP found")
}