// Copyright 2018 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 prototype

import (
	"fmt"
	"math"
	"strconv"
	"strings"

	descriptorV1 "github.com/golang/protobuf/protoc-gen-go/descriptor"

	"google.golang.org/proto/internal/encoding/text"
	"google.golang.org/proto/internal/errors"
	"google.golang.org/proto/reflect/protoreflect"
	"google.golang.org/proto/reflect/protoregistry"
)

// TODO: Should we be responsible for validating other parts of the descriptor
// that we don't directly use?
//
// For example:
//	* That field numbers don't overlap with reserved numbers.
//	* That field names don't overlap with reserved names.
//	* That enum numbers don't overlap with reserved numbers.
//	* That enum names don't overlap with reserved names.
//	* That "extendee" is not set for a message field.
//	* That "oneof_index" is not set for an extension field.
//	* That "json_name" is not set for an extension field. Maybe, maybe not.
//	* That "type_name" is not set on a field for non-enums and non-messages.
//	* That "weak" is not set for an extension field (double check this).

// TODO: Store the input file descriptor to implement:
//	* protoreflect.Descriptor.DescriptorProto
//	* protoreflect.Descriptor.DescriptorOptions

// TODO: Should we return a File instead of protoreflect.FileDescriptor?
// This would allow users to mutate the File before converting it.
// However, this will complicate future work for validation since File may now
// diverge from the stored descriptor proto (see above TODO).

// NewFileFromDescriptorProto creates a new protoreflect.FileDescriptor from
// the provided descriptor message. The file must represent a valid proto file
// according to protobuf semantics.
//
// Any import files, enum types, or message types referenced in the file are
// resolved using the provided registry. When looking up an import file path,
// the path must be unique. The newly created file descriptor is not registered
// back into the provided file registry.
//
// The caller must relinquish full ownership of the input fd and must not
// access or mutate any fields.
func NewFileFromDescriptorProto(fd *descriptorV1.FileDescriptorProto, r *protoregistry.Files) (protoreflect.FileDescriptor, error) {
	var f File
	switch fd.GetSyntax() {
	case "proto2":
		f.Syntax = protoreflect.Proto2
	case "proto3":
		f.Syntax = protoreflect.Proto3
	default:
		return nil, errors.New("invalid syntax: %v", fd.GetSyntax())
	}
	f.Path = fd.GetName()
	f.Package = protoreflect.FullName(fd.GetPackage())

	f.Imports = make([]protoreflect.FileImport, len(fd.GetDependency()))
	for _, i := range fd.GetPublicDependency() {
		if int(i) >= len(f.Imports) || f.Imports[i].IsPublic {
			return nil, errors.New("invalid or duplicate public import index: %d", i)
		}
		f.Imports[i].IsPublic = true
	}
	for _, i := range fd.GetWeakDependency() {
		if int(i) >= len(f.Imports) || f.Imports[i].IsWeak {
			return nil, errors.New("invalid or duplicate weak import index: %d", i)
		}
		f.Imports[i].IsWeak = true
	}
	for i, path := range fd.GetDependency() {
		var n int
		imp := &f.Imports[i]
		r.RangeFilesByPath(path, func(fd protoreflect.FileDescriptor) bool {
			imp.FileDescriptor = fd
			n++
			return true
		})
		if n > 1 {
			return nil, errors.New("duplicate files for import %q", path)
		}
		if imp.IsWeak || imp.FileDescriptor == nil {
			imp.FileDescriptor = PlaceholderFile(path, "")
		}
	}

	var err error
	f.Messages, err = messagesFromDescriptorProto(fd.GetMessageType(), r)
	if err != nil {
		return nil, err
	}
	f.Enums, err = enumsFromDescriptorProto(fd.GetEnumType(), r)
	if err != nil {
		return nil, err
	}
	f.Extensions, err = extensionsFromDescriptorProto(fd.GetExtension(), r)
	if err != nil {
		return nil, err
	}
	f.Services, err = servicesFromDescriptorProto(fd.GetService(), r)
	if err != nil {
		return nil, err
	}

	return NewFile(&f)
}

func messagesFromDescriptorProto(mds []*descriptorV1.DescriptorProto, r *protoregistry.Files) (ms []Message, err error) {
	for _, md := range mds {
		var m Message
		m.Name = protoreflect.Name(md.GetName())
		m.IsMapEntry = md.GetOptions().GetMapEntry()
		for _, fd := range md.GetField() {
			var f Field
			f.Name = protoreflect.Name(fd.GetName())
			f.Number = protoreflect.FieldNumber(fd.GetNumber())
			f.Cardinality = protoreflect.Cardinality(fd.GetLabel())
			f.Kind = protoreflect.Kind(fd.GetType())
			f.JSONName = fd.GetJsonName()
			f.IsPacked = fd.GetOptions().GetPacked()
			f.IsWeak = fd.GetOptions().GetWeak()
			if fd.DefaultValue != nil {
				f.Default, err = parseDefault(fd.GetDefaultValue(), f.Kind)
				if err != nil {
					return nil, err
				}
			}
			if fd.OneofIndex != nil {
				i := int(fd.GetOneofIndex())
				if i >= len(md.GetOneofDecl()) {
					return nil, errors.New("invalid oneof index: %d", i)
				}
				f.OneofName = protoreflect.Name(md.GetOneofDecl()[i].GetName())
			}
			switch f.Kind {
			case protoreflect.EnumKind:
				f.EnumType, err = findEnumDescriptor(fd.GetTypeName(), r)
				if err != nil {
					return nil, err
				}
				if f.IsWeak && !f.EnumType.IsPlaceholder() {
					f.EnumType = PlaceholderEnum(f.EnumType.FullName())
				}
			case protoreflect.MessageKind, protoreflect.GroupKind:
				f.MessageType, err = findMessageDescriptor(fd.GetTypeName(), r)
				if err != nil {
					return nil, err
				}
				if f.IsWeak && !f.MessageType.IsPlaceholder() {
					f.MessageType = PlaceholderMessage(f.MessageType.FullName())
				}
			}
			m.Fields = append(m.Fields, f)
		}
		for _, od := range md.GetOneofDecl() {
			m.Oneofs = append(m.Oneofs, Oneof{Name: protoreflect.Name(od.GetName())})
		}
		for _, xr := range md.GetExtensionRange() {
			m.ExtensionRanges = append(m.ExtensionRanges, [2]protoreflect.FieldNumber{
				protoreflect.FieldNumber(xr.GetStart()),
				protoreflect.FieldNumber(xr.GetEnd()),
			})
		}

		m.Messages, err = messagesFromDescriptorProto(md.GetNestedType(), r)
		if err != nil {
			return nil, err
		}
		m.Enums, err = enumsFromDescriptorProto(md.GetEnumType(), r)
		if err != nil {
			return nil, err
		}
		m.Extensions, err = extensionsFromDescriptorProto(md.GetExtension(), r)
		if err != nil {
			return nil, err
		}

		ms = append(ms, m)
	}
	return ms, nil
}

func enumsFromDescriptorProto(eds []*descriptorV1.EnumDescriptorProto, r *protoregistry.Files) (es []Enum, err error) {
	for _, ed := range eds {
		var e Enum
		e.Name = protoreflect.Name(ed.GetName())
		for _, vd := range ed.GetValue() {
			e.Values = append(e.Values, EnumValue{
				Name:   protoreflect.Name(vd.GetName()),
				Number: protoreflect.EnumNumber(vd.GetNumber()),
			})
		}
		es = append(es, e)
	}
	return es, nil
}

func extensionsFromDescriptorProto(xds []*descriptorV1.FieldDescriptorProto, r *protoregistry.Files) (xs []Extension, err error) {
	for _, xd := range xds {
		var x Extension
		x.Name = protoreflect.Name(xd.GetName())
		x.Number = protoreflect.FieldNumber(xd.GetNumber())
		x.Cardinality = protoreflect.Cardinality(xd.GetLabel())
		x.Kind = protoreflect.Kind(xd.GetType())
		x.IsPacked = xd.GetOptions().GetPacked()
		if xd.DefaultValue != nil {
			x.Default, err = parseDefault(xd.GetDefaultValue(), x.Kind)
			if err != nil {
				return nil, err
			}
		}
		switch x.Kind {
		case protoreflect.EnumKind:
			x.EnumType, err = findEnumDescriptor(xd.GetTypeName(), r)
			if err != nil {
				return nil, err
			}
		case protoreflect.MessageKind, protoreflect.GroupKind:
			x.MessageType, err = findMessageDescriptor(xd.GetTypeName(), r)
			if err != nil {
				return nil, err
			}
		}
		x.ExtendedType, err = findMessageDescriptor(xd.GetExtendee(), r)
		if err != nil {
			return nil, err
		}
		xs = append(xs, x)
	}
	return xs, nil
}

func servicesFromDescriptorProto(sds []*descriptorV1.ServiceDescriptorProto, r *protoregistry.Files) (ss []Service, err error) {
	for _, sd := range sds {
		var s Service
		s.Name = protoreflect.Name(sd.GetName())
		for _, md := range sd.GetMethod() {
			var m Method
			m.Name = protoreflect.Name(md.GetName())
			m.InputType, err = findMessageDescriptor(md.GetInputType(), r)
			if err != nil {
				return nil, err
			}
			m.OutputType, err = findMessageDescriptor(md.GetOutputType(), r)
			if err != nil {
				return nil, err
			}
			m.IsStreamingClient = md.GetClientStreaming()
			m.IsStreamingServer = md.GetServerStreaming()
			s.Methods = append(s.Methods, m)
		}
		ss = append(ss, s)
	}
	return ss, nil
}

// TODO: Should we allow relative names? The protoc compiler has emitted
// absolute names for some time now. Requiring absolute names as an input
// simplifies our implementation as we won't need to implement C++'s namespace
// scoping rules.

func findMessageDescriptor(s string, r *protoregistry.Files) (protoreflect.MessageDescriptor, error) {
	if !strings.HasPrefix(s, ".") {
		return nil, errors.New("identifier name must be fully qualified with a leading dot: %v", s)
	}
	name := protoreflect.FullName(strings.TrimPrefix(s, "."))
	switch m, err := r.FindDescriptorByName(name); {
	case err == nil:
		m, ok := m.(protoreflect.MessageDescriptor)
		if !ok {
			return nil, errors.New("resolved wrong type: got %v, want message", typeName(m))
		}
		return m, nil
	case err == protoregistry.NotFound:
		return PlaceholderMessage(name), nil
	default:
		return nil, err
	}
}

func findEnumDescriptor(s string, r *protoregistry.Files) (protoreflect.EnumDescriptor, error) {
	if !strings.HasPrefix(s, ".") {
		return nil, errors.New("identifier name must be fully qualified with a leading dot: %v", s)
	}
	name := protoreflect.FullName(strings.TrimPrefix(s, "."))
	switch e, err := r.FindDescriptorByName(name); {
	case err == nil:
		e, ok := e.(protoreflect.EnumDescriptor)
		if !ok {
			return nil, errors.New("resolved wrong type: got %T, want enum", typeName(e))
		}
		return e, nil
	case err == protoregistry.NotFound:
		return PlaceholderEnum(name), nil
	default:
		return nil, err
	}
}

func typeName(t protoreflect.Descriptor) string {
	switch t.(type) {
	case protoreflect.EnumType:
		return "enum"
	case protoreflect.MessageType:
		return "message"
	default:
		return fmt.Sprintf("%T", t)
	}
}

func parseDefault(s string, k protoreflect.Kind) (protoreflect.Value, error) {
	switch k {
	case protoreflect.BoolKind:
		switch s {
		case "true":
			return protoreflect.ValueOf(true), nil
		case "false":
			return protoreflect.ValueOf(false), nil
		}
	case protoreflect.EnumKind:
		// For enums, we are supposed to return a protoreflect.EnumNumber type.
		// However, default values record the name instead of the number.
		// We are unable to resolve the name into a number without additional
		// type information. Thus, we temporarily return the name identifier
		// for now and rely on logic in defaultValue.lazyInit to resolve it.
		return protoreflect.ValueOf(s), nil
	case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
		v, err := strconv.ParseInt(s, 0, 32)
		if err == nil {
			return protoreflect.ValueOf(int32(v)), nil
		}
	case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
		v, err := strconv.ParseInt(s, 0, 64)
		if err == nil {
			return protoreflect.ValueOf(int64(v)), nil
		}
	case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
		v, err := strconv.ParseUint(s, 0, 32)
		if err == nil {
			return protoreflect.ValueOf(uint64(v)), nil
		}
	case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
		v, err := strconv.ParseUint(s, 0, 64)
		if err == nil {
			return protoreflect.ValueOf(uint64(v)), nil
		}
	case protoreflect.FloatKind, protoreflect.DoubleKind:
		var v float64
		var err error
		switch s {
		case "nan":
			v = math.NaN()
		case "inf":
			v = math.Inf(+1)
		case "-inf":
			v = math.Inf(-1)
		default:
			v, err = strconv.ParseFloat(s, 64)
		}
		if err == nil {
			if k == protoreflect.FloatKind {
				return protoreflect.ValueOf(float32(v)), nil
			}
			return protoreflect.ValueOf(float64(v)), nil
		}
	case protoreflect.StringKind, protoreflect.BytesKind:
		// String values use the same escaping as the text format,
		// however they lack the surrounding double quotes.
		// TODO: Export unmarshalString in the text package to avoid this hack.
		v, err := text.Unmarshal([]byte(`["` + s + `"]:0`))
		if err == nil && len(v.Message()) == 1 {
			s := v.Message()[0][0].String()
			if k == protoreflect.StringKind {
				return protoreflect.ValueOf(s), nil
			}
			return protoreflect.ValueOf([]byte(s)), nil
		}
	}
	return protoreflect.Null, errors.New("invalid default value for %v: %q", k, s)
}
