// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package protocmp

import (
	"reflect"
	"sort"
	"strconv"
	"strings"

	"google.golang.org/protobuf/proto"
	"google.golang.org/protobuf/reflect/protoreflect"
	"google.golang.org/protobuf/runtime/protoiface"
)

func reflectValueOf(v interface{}) protoreflect.Value {
	switch v := v.(type) {
	case Enum:
		return protoreflect.ValueOfEnum(v.Number())
	case Message:
		return protoreflect.ValueOfMessage(v.ProtoReflect())
	case []byte:
		return protoreflect.ValueOfBytes(v) // avoid overlap with reflect.Slice check below
	default:
		switch rv := reflect.ValueOf(v); {
		case rv.Kind() == reflect.Slice:
			return protoreflect.ValueOfList(reflectList{rv})
		case rv.Kind() == reflect.Map:
			return protoreflect.ValueOfMap(reflectMap{rv})
		default:
			return protoreflect.ValueOf(v)
		}
	}
}

type reflectMessage Message

func (m reflectMessage) stringKey(fd protoreflect.FieldDescriptor) string {
	if m.Descriptor() != fd.Parent() {
		panic("mismatching containing message")
	}
	if fd.IsExtension() {
		return string("[" + fd.FullName() + "]")
	}
	return string(fd.Name())
}

func (m reflectMessage) Descriptor() protoreflect.MessageDescriptor {
	return (Message)(m).Descriptor()
}
func (m reflectMessage) Type() protoreflect.MessageType {
	return reflectMessageType{m.Descriptor()}
}
func (m reflectMessage) New() protoreflect.Message {
	return m.Type().New()
}
func (m reflectMessage) Interface() protoreflect.ProtoMessage {
	return Message(m)
}
func (m reflectMessage) Range(f func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool) {
	// Range over populated known fields.
	fds := m.Descriptor().Fields()
	for i := 0; i < fds.Len(); i++ {
		fd := fds.Get(i)
		if m.Has(fd) && !f(fd, m.Get(fd)) {
			return
		}
	}

	// Range over populated extension fields.
	for _, xd := range m[messageTypeKey].(messageType).xds {
		if m.Has(xd) && !f(xd, m.Get(xd)) {
			return
		}
	}
}
func (m reflectMessage) Has(fd protoreflect.FieldDescriptor) bool {
	_, ok := m[m.stringKey(fd)]
	return ok
}
func (m reflectMessage) Clear(protoreflect.FieldDescriptor) {
	panic("invalid mutation of read-only message")
}
func (m reflectMessage) Get(fd protoreflect.FieldDescriptor) protoreflect.Value {
	v, ok := m[m.stringKey(fd)]
	if !ok {
		switch {
		case fd.IsList():
			return protoreflect.ValueOfList(reflectList{})
		case fd.IsMap():
			return protoreflect.ValueOfMap(reflectMap{})
		case fd.Message() != nil:
			return protoreflect.ValueOfMessage(reflectMessage{
				messageTypeKey: messageType{md: m.Descriptor()},
			})
		default:
			return fd.Default()
		}
	}

	// The transformation may leave Any messages in structured form.
	// If so, convert them back to a raw-encoded form.
	if fd.FullName() == "google.protobuf.Any.value" {
		if m, ok := v.(Message); ok {
			b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
			if err != nil {
				panic("BUG: " + err.Error())
			}
			return protoreflect.ValueOfBytes(b)
		}
	}

	return reflectValueOf(v)
}
func (m reflectMessage) Set(protoreflect.FieldDescriptor, protoreflect.Value) {
	panic("invalid mutation of read-only message")
}
func (m reflectMessage) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value {
	panic("invalid mutation of read-only message")
}
func (m reflectMessage) NewField(protoreflect.FieldDescriptor) protoreflect.Value {
	panic("not implemented")
}
func (m reflectMessage) WhichOneof(od protoreflect.OneofDescriptor) protoreflect.FieldDescriptor {
	if m.Descriptor().Oneofs().ByName(od.Name()) != od {
		panic("oneof descriptor does not belong to this message")
	}
	fds := od.Fields()
	for i := 0; i < fds.Len(); i++ {
		fd := fds.Get(i)
		if _, ok := m[m.stringKey(fd)]; ok {
			return fd
		}
	}
	return nil
}
func (m reflectMessage) GetUnknown() protoreflect.RawFields {
	var nums []protoreflect.FieldNumber
	for k := range m {
		if len(strings.Trim(k, "0123456789")) == 0 {
			n, _ := strconv.ParseUint(k, 10, 32)
			nums = append(nums, protoreflect.FieldNumber(n))
		}
	}
	sort.Slice(nums, func(i, j int) bool { return nums[i] < nums[j] })

	var raw protoreflect.RawFields
	for _, num := range nums {
		b, _ := m[strconv.FormatUint(uint64(num), 10)].(protoreflect.RawFields)
		raw = append(raw, b...)
	}
	return raw
}
func (m reflectMessage) SetUnknown(protoreflect.RawFields) {
	panic("invalid mutation of read-only message")
}
func (m reflectMessage) IsValid() bool {
	invalid, _ := m[messageInvalidKey].(bool)
	return !invalid
}
func (m reflectMessage) ProtoMethods() *protoiface.Methods {
	return nil
}

type reflectMessageType struct{ protoreflect.MessageDescriptor }

func (t reflectMessageType) New() protoreflect.Message {
	panic("not implemented")
}
func (t reflectMessageType) Zero() protoreflect.Message {
	panic("not implemented")
}
func (t reflectMessageType) Descriptor() protoreflect.MessageDescriptor {
	return t.MessageDescriptor
}

type reflectList struct{ v reflect.Value }

func (ls reflectList) Len() int {
	if !ls.IsValid() {
		return 0
	}
	return ls.v.Len()
}
func (ls reflectList) Get(i int) protoreflect.Value {
	return reflectValueOf(ls.v.Index(i).Interface())
}
func (ls reflectList) Set(int, protoreflect.Value) {
	panic("invalid mutation of read-only list")
}
func (ls reflectList) Append(protoreflect.Value) {
	panic("invalid mutation of read-only list")
}
func (ls reflectList) AppendMutable() protoreflect.Value {
	panic("invalid mutation of read-only list")
}
func (ls reflectList) Truncate(int) {
	panic("invalid mutation of read-only list")
}
func (ls reflectList) NewElement() protoreflect.Value {
	panic("not implemented")
}
func (ls reflectList) IsValid() bool {
	return ls.v.IsValid()
}

type reflectMap struct{ v reflect.Value }

func (ms reflectMap) Len() int {
	if !ms.IsValid() {
		return 0
	}
	return ms.v.Len()
}
func (ms reflectMap) Range(f func(protoreflect.MapKey, protoreflect.Value) bool) {
	if !ms.IsValid() {
		return
	}
	ks := ms.v.MapKeys()
	for _, k := range ks {
		pk := reflectValueOf(k.Interface()).MapKey()
		pv := reflectValueOf(ms.v.MapIndex(k).Interface())
		if !f(pk, pv) {
			return
		}
	}
}
func (ms reflectMap) Has(k protoreflect.MapKey) bool {
	if !ms.IsValid() {
		return false
	}
	return ms.v.MapIndex(reflect.ValueOf(k.Interface())).IsValid()
}
func (ms reflectMap) Clear(protoreflect.MapKey) {
	panic("invalid mutation of read-only list")
}
func (ms reflectMap) Get(k protoreflect.MapKey) protoreflect.Value {
	if !ms.IsValid() {
		return protoreflect.Value{}
	}
	v := ms.v.MapIndex(reflect.ValueOf(k.Interface()))
	if !v.IsValid() {
		return protoreflect.Value{}
	}
	return reflectValueOf(v.Interface())
}
func (ms reflectMap) Set(protoreflect.MapKey, protoreflect.Value) {
	panic("invalid mutation of read-only list")
}
func (ms reflectMap) Mutable(k protoreflect.MapKey) protoreflect.Value {
	panic("invalid mutation of read-only list")
}
func (ms reflectMap) NewValue() protoreflect.Value {
	panic("not implemented")
}
func (ms reflectMap) IsValid() bool {
	return ms.v.IsValid()
}
