package dagro

import (
	
	
)

type optionalEdgeName struct{ value *string }

func isCallable( any) bool {
	 := reflect.ValueOf()
	return .IsValid() && .Kind() == reflect.Func
}

// callCallable adapts JavaScript-style callbacks to Go. JavaScript ignores
// surplus arguments and supplies undefined for missing ones; Go's zero value
// is the closest representable value for a missing statically typed argument.
func callCallable( any,  ...any) any {
	 := reflect.ValueOf()
	if !.IsValid() || .Kind() != reflect.Func {
		panic(fmt.Sprintf("dagro: expected callback, got %T", ))
	}
	if .IsNil() {
		return nil
	}
	 := .Type()
	if .NumOut() > 1 {
		panic(fmt.Sprintf("dagro: callback %T returns more than one value", ))
	}

	 := .NumIn()
	if .IsVariadic() {
		--
	}
	 := make([]reflect.Value, 0, .NumIn()+len())
	for  := 0;  < ; ++ {
		if  < len() {
			 = append(, callbackArgument([], .In()))
		} else {
			 = append(, reflect.Zero(.In()))
		}
	}
	if .IsVariadic() {
		 := .In(.NumIn() - 1).Elem()
		for  := ;  < len(); ++ {
			 = append(, callbackArgument([], ))
		}
	}

	 := .Call()
	if len() == 0 {
		return nil
	}
	return [0].Interface()
}

func callbackArgument( any,  reflect.Type) reflect.Value {
	if ,  := .(optionalEdgeName);  {
		switch {
		case .Kind() == reflect.Pointer && .Elem().Kind() == reflect.String:
			if .value == nil {
				return reflect.Zero()
			}
			return convertCallbackValue(reflect.ValueOf(.value), )
		case .value == nil:
			return reflect.Zero()
		default:
			return convertCallbackValue(reflect.ValueOf(*.value), )
		}
	}
	if  == nil {
		return reflect.Zero()
	}
	return convertCallbackValue(reflect.ValueOf(), )
}

func convertCallbackValue( reflect.Value,  reflect.Type) reflect.Value {
	if .Type().AssignableTo() {
		return 
	}
	if .Type().ConvertibleTo() {
		return .Convert()
	}
	panic(fmt.Sprintf("dagro: callback argument %s is not assignable to %s", .Type(), ))
}