// 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 any) 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].(messageMeta).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: messageMeta{md: fd.Message()},
			})
		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()
}
