//+build go1.12

package dynamic

import (
	"github.com/jhump/protoreflect/desc"
	"reflect"
)

// With Go 1.12 and above, we can use reflect.Value.MapRange to iterate
// over maps more efficiently than using reflect.Value.MapKeys.

func mapsEqual(a, b reflect.Value) bool {
	if a.Len() != b.Len() {
		return false
	}
	if a.Len() == 0 && b.Len() == 0 {
		// Optimize the case where maps are frequently empty
		return true
	}

	iter := a.MapRange()
	for iter.Next() {
		k := iter.Key()
		av := iter.Value()
		bv := b.MapIndex(k)
		if !bv.IsValid() {
			return false
		}
		if !fieldsEqual(av.Interface(), bv.Interface()) {
			return false
		}
	}
	return true
}

func validFieldValueForMapField(fd *desc.FieldDescriptor, val reflect.Value) (interface{}, error) {
	// make a defensive copy while we check the contents
	// (also converts to map[interface{}]interface{} if it's some other type)
	keyField := fd.GetMessageType().GetFields()[0]
	valField := fd.GetMessageType().GetFields()[1]
	m := map[interface{}]interface{}{}
	iter := val.MapRange()
	for iter.Next() {
		k := iter.Key()
		if k.Kind() == reflect.Interface {
			// unwrap it
			k = reflect.ValueOf(k.Interface())
		}
		kk, err := validFieldValueForRv(keyField, k)
		if err != nil {
			return nil, err
		}
		v := iter.Value()
		if v.Kind() == reflect.Interface {
			// unwrap it
			v = reflect.ValueOf(v.Interface())
		}
		vv, err := validFieldValueForRv(valField, v)
		if err != nil {
			return nil, err
		}
		m[kk] = vv
	}
	return m, nil
}

func canConvertMap(src reflect.Value, target reflect.Type) bool {
	kt := target.Key()
	vt := target.Elem()
	iter := src.MapRange()
	for iter.Next() {
		if !canConvert(iter.Key(), kt) {
			return false
		}
		if !canConvert(iter.Value(), vt) {
			return false
		}
	}
	return true
}

func mergeMapVal(src, target reflect.Value, targetType reflect.Type) error {
	tkt := targetType.Key()
	tvt := targetType.Elem()
	iter := src.MapRange()
	for iter.Next() {
		k := iter.Key()
		v := iter.Value()
		skt := k.Type()
		svt := v.Type()
		var nk, nv reflect.Value
		if tkt == skt {
			nk = k
		} else if tkt.Kind() == reflect.Ptr && tkt.Elem() == skt {
			nk = k.Addr()
		} else {
			nk = reflect.New(tkt).Elem()
			if err := mergeVal(k, nk); err != nil {
				return err
			}
		}
		if tvt == svt {
			nv = v
		} else if tvt.Kind() == reflect.Ptr && tvt.Elem() == svt {
			nv = v.Addr()
		} else {
			nv = reflect.New(tvt).Elem()
			if err := mergeVal(v, nv); err != nil {
				return err
			}
		}
		if target.IsNil() {
			target.Set(reflect.MakeMap(targetType))
		}
		target.SetMapIndex(nk, nv)
	}
	return nil
}

func mergeMapField(m *Message, fd *desc.FieldDescriptor, rv reflect.Value) error {
	iter := rv.MapRange()
	for iter.Next() {
		k := iter.Key()
		v := iter.Value()
		if k.Kind() == reflect.Interface && !k.IsNil() {
			k = k.Elem()
		}
		if v.Kind() == reflect.Interface && !v.IsNil() {
			v = v.Elem()
		}
		if err := m.putMapField(fd, k.Interface(), v.Interface()); err != nil {
			return err
		}
	}
	return nil
}
