// 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/internal/genid"
	"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.ContainingMessage() {
		panic("mismatching containing message")
	}
	return fd.TextName()
}

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() == genid.Any_Value_field_fullname {
		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()
}
