// 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 protoregistry provides data structures to register and lookup
// protobuf descriptor types.
//
// The Files registry contains file descriptors and provides the ability
// to iterate over the files or lookup a specific descriptor within the files.
// Files only contains protobuf descriptors and has no understanding of Go
// type information that may be associated with each descriptor.
//
// The Types registry contains descriptor types for which there is a known
// Go type associated with that descriptor. It provides the ability to iterate
// over the registered types or lookup a type by name.
package protoregistry

import (
	"fmt"
	"reflect"
	"sort"
	"strings"

	"github.com/golang/protobuf/v2/internal/errors"
	"github.com/golang/protobuf/v2/reflect/protoreflect"
)

// TODO: Perhaps Register should record the frame of where the function was
// called and surface that in the error? That would help users debug duplicate
// registration issues. This presumes that we provide a way to disable automatic
// registration in generated code.

// GlobalFiles is a global registry of file descriptors.
var GlobalFiles *Files = new(Files)

// GlobalTypes is the registry used by default for type lookups
// unless a local registry is provided by the user.
var GlobalTypes *Types = new(Types)

// NotFound is a sentinel error value to indicate that the type was not found.
var NotFound = errors.New("not found")

// Files is a registry for looking up or iterating over files and the
// descriptors contained within them.
// The Find and Range methods are safe for concurrent use.
type Files struct {
	filesByPackage filesByPackage
	filesByPath    filesByPath
}

type (
	filesByPackage struct {
		// files is a list of files all in the same package.
		files []protoreflect.FileDescriptor
		// subs is a tree of files all in a sub-package scope.
		// It also maps all top-level identifiers declared in files
		// as the notProtoPackage sentinel value.
		subs map[protoreflect.Name]*filesByPackage // invariant: len(Name) > 0
	}
	filesByPath map[string][]protoreflect.FileDescriptor
)

// notProtoPackage is a sentinel value to indicate that some identifier maps
// to an actual protobuf declaration and is not a sub-package.
var notProtoPackage = new(filesByPackage)

// NewFiles returns a registry initialized with the provided set of files.
// If there are duplicates, the first one takes precedence.
func NewFiles(files ...protoreflect.FileDescriptor) *Files {
	// TODO: Should last take precedence? This allows a user to intentionally
	// overwrite an existing registration.
	//
	// The use case is for implementing the existing v1 proto.RegisterFile
	// function where the behavior is last wins. However, it could be argued
	// that the v1 behavior is broken, and we can switch to first wins
	// without violating compatibility.
	r := new(Files)
	r.Register(files...) // ignore errors; first takes precedence
	return r
}

// Register registers the provided list of file descriptors.
// Placeholder files are ignored.
//
// If any descriptor within a file conflicts with the descriptor of any
// previously registered file (e.g., two enums with the same full name),
// then that file is not registered and an error is returned.
//
// It is permitted for multiple files to have the same file path.
func (r *Files) Register(files ...protoreflect.FileDescriptor) error {
	var firstErr error
fileLoop:
	for _, file := range files {
		if file.IsPlaceholder() {
			continue // TODO: Should this be an error instead?
		}

		// Register the file into the filesByPackage tree.
		//
		// The prototype package validates that a FileDescriptor is internally
		// consistent such it does not have conflicts within itself.
		// However, we need to ensure that the inserted file does not conflict
		// with other previously inserted files.
		pkg := file.Package()
		root := &r.filesByPackage
		for len(pkg) > 0 {
			var prefix protoreflect.Name
			prefix, pkg = splitPrefix(pkg)

			// Add a new sub-package segment.
			switch nextRoot := root.subs[prefix]; nextRoot {
			case nil:
				nextRoot = new(filesByPackage)
				if root.subs == nil {
					root.subs = make(map[protoreflect.Name]*filesByPackage)
				}
				root.subs[prefix] = nextRoot
				root = nextRoot
			case notProtoPackage:
				if firstErr == nil {
					name := strings.TrimSuffix(strings.TrimSuffix(string(file.Package()), string(pkg)), ".")
					firstErr = errors.New("file %q has a name conflict over %v", file.Path(), name)
				}
				continue fileLoop
			default:
				root = nextRoot
			}
		}
		// Check for top-level conflicts within the same package.
		// The current file cannot add any top-level declaration that conflict
		// with another top-level declaration or sub-package name.
		var conflicts []protoreflect.Name
		rangeTopLevelDeclarations(file, func(s protoreflect.Name) {
			if root.subs[s] == nil {
				if root.subs == nil {
					root.subs = make(map[protoreflect.Name]*filesByPackage)
				}
				root.subs[s] = notProtoPackage
			} else {
				conflicts = append(conflicts, s)
			}
		})
		if len(conflicts) > 0 {
			// Remove inserted identifiers to make registration failure atomic.
			sort.Slice(conflicts, func(i, j int) bool { return conflicts[i] < conflicts[j] })
			rangeTopLevelDeclarations(file, func(s protoreflect.Name) {
				i := sort.Search(len(conflicts), func(i int) bool { return conflicts[i] >= s })
				if has := i < len(conflicts) && conflicts[i] == s; !has {
					delete(root.subs, s) // remove everything not in conflicts
				}
			})

			if firstErr == nil {
				name := file.Package().Append(conflicts[0])
				firstErr = errors.New("file %q has a name conflict over %v", file.Path(), name)
			}
			continue fileLoop
		}
		root.files = append(root.files, file)

		// Register the file into the filesByPath map.
		//
		// There is no check for conflicts in file path since the path is
		// heavily dependent on how protoc is invoked. When protoc is being
		// invoked by different parties in a distributed manner, it is
		// unreasonable to assume nor ensure that the path is unique.
		if r.filesByPath == nil {
			r.filesByPath = make(filesByPath)
		}
		r.filesByPath[file.Path()] = append(r.filesByPath[file.Path()], file)
	}
	return firstErr
}

// FindDescriptorByName looks up any descriptor (except files) by its full name.
// Files are not handled since multiple file descriptors may belong in
// the same package and have the same full name (see RangeFilesByPackage).
//
// This return (nil, NotFound) if not found.
func (r *Files) FindDescriptorByName(name protoreflect.FullName) (protoreflect.Descriptor, error) {
	if r == nil {
		return nil, NotFound
	}
	pkg := name
	root := &r.filesByPackage
	for len(pkg) > 0 {
		var prefix protoreflect.Name
		prefix, pkg = splitPrefix(pkg)
		switch nextRoot := root.subs[prefix]; nextRoot {
		case nil:
			return nil, NotFound
		case notProtoPackage:
			// Search current root's package for the descriptor.
			for _, fd := range root.files {
				if d := fd.DescriptorByName(name); d != nil {
					return d, nil
				}
			}
			return nil, NotFound
		default:
			root = nextRoot
		}
	}
	return nil, NotFound
}

// RangeFiles iterates over all registered files.
// The iteration order is undefined.
func (r *Files) RangeFiles(f func(protoreflect.FileDescriptor) bool) {
	r.RangeFilesByPackage("", f) // empty package is a prefix for all packages
}

// RangeFilesByPackage iterates over all registered files filtered by
// the given proto package prefix. It iterates over files with an exact package
// match before iterating over files with general prefix match.
// The iteration order is undefined within exact matches or prefix matches.
func (r *Files) RangeFilesByPackage(pkg protoreflect.FullName, f func(protoreflect.FileDescriptor) bool) {
	if r == nil {
		return
	}
	if strings.HasSuffix(string(pkg), ".") {
		return // avoid edge case where splitPrefix allows trailing dot
	}
	root := &r.filesByPackage
	for len(pkg) > 0 && root != nil {
		var prefix protoreflect.Name
		prefix, pkg = splitPrefix(pkg)
		root = root.subs[prefix]
	}
	rangeFiles(root, f)
}
func rangeFiles(fs *filesByPackage, f func(protoreflect.FileDescriptor) bool) bool {
	if fs == nil {
		return true
	}
	// Iterate over exact matches.
	for _, fd := range fs.files { // TODO: iterate non-deterministically
		if !f(fd) {
			return false
		}
	}
	// Iterate over prefix matches.
	for _, fs := range fs.subs {
		if !rangeFiles(fs, f) {
			return false
		}
	}
	return true
}

// RangeFilesByPath iterates over all registered files filtered by
// the given proto path. The iteration order is undefined.
func (r *Files) RangeFilesByPath(path string, f func(protoreflect.FileDescriptor) bool) {
	if r == nil {
		return
	}
	for _, fd := range r.filesByPath[path] { // TODO: iterate non-deterministically
		if !f(fd) {
			return
		}
	}
}

func splitPrefix(name protoreflect.FullName) (protoreflect.Name, protoreflect.FullName) {
	if i := strings.IndexByte(string(name), '.'); i >= 0 {
		return protoreflect.Name(name[:i]), name[i+len("."):]
	}
	return protoreflect.Name(name), ""
}

// rangeTopLevelDeclarations iterates over the name of all top-level
// declarations in the proto file.
func rangeTopLevelDeclarations(fd protoreflect.FileDescriptor, f func(protoreflect.Name)) {
	for i := 0; i < fd.Enums().Len(); i++ {
		e := fd.Enums().Get(i)
		f(e.Name())
		for i := 0; i < e.Values().Len(); i++ {
			f(e.Values().Get(i).Name())
		}
	}
	for i := 0; i < fd.Messages().Len(); i++ {
		f(fd.Messages().Get(i).Name())
	}
	for i := 0; i < fd.Extensions().Len(); i++ {
		f(fd.Extensions().Get(i).Name())
	}
	for i := 0; i < fd.Services().Len(); i++ {
		f(fd.Services().Get(i).Name())
	}
}

// Type is an interface satisfied by protoreflect.EnumType,
// protoreflect.MessageType, or protoreflect.ExtensionType.
type Type interface {
	protoreflect.Descriptor
	GoType() reflect.Type
}

var (
	_ Type = protoreflect.EnumType(nil)
	_ Type = protoreflect.MessageType(nil)
	_ Type = protoreflect.ExtensionType(nil)
)

// Types is a registry for looking up or iterating over descriptor types.
// The Find and Range methods are safe for concurrent use.
type Types struct {
	// Parent sets the parent registry to consult if a find operation
	// could not locate the appropriate entry.
	//
	// Setting a parent results in each Range operation also iterating over the
	// entries contained within the parent. In such a case, it is possible for
	// Range to emit duplicates (since they may exist in both child and parent).
	// Range iteration is guaranteed to iterate over local entries before
	// iterating over parent entries.
	Parent *Types

	// Resolver sets the local resolver to consult if the local registry does
	// not contain an entry. The resolver takes precedence over the parent.
	//
	// The url is a URL where the full name of the type is the last segment
	// of the path (i.e. string following the last '/' character).
	// When missing a '/' character, the URL is the full name of the type.
	// See documentation on the google.protobuf.Any.type_url field for details.
	//
	// If the resolver returns a result, it is not automatically registered
	// into the local registry. Thus, a resolver function should cache results
	// such that it deterministically returns the same result given the
	// same URL assuming the error returned is nil or NotFound.
	//
	// If the resolver returns the NotFound error, the registry will consult the
	// parent registry if it is set.
	//
	// Setting a resolver has no effect on the result of each Range operation.
	Resolver func(url string) (Type, error)

	// TODO: The syntax of the URL is ill-defined and the protobuf team recently
	// changed the documented semantics in a way that breaks prior usages.
	// I do not believe they can do this and need to sync up with the
	// protobuf team again to hash out what the proper syntax of the URL is.

	// TODO: Should we separate this out as a registry for each type?
	//
	// In Java, the extension and message registry are distinct classes.
	// Their extension registry has knowledge of distinct Java types,
	// while their message registry only contains descriptor information.
	//
	// In Go, we have always registered messages, enums, and extensions.
	// Messages and extensions are registered with Go information, while enums
	// are only registered with descriptor information. We cannot drop Go type
	// information for messages otherwise we would be unable to implement
	// portions of the v1 API such as ptypes.DynamicAny.
	//
	// There is no enum registry in Java. In v1, we used the enum registry
	// because enum types provided no reflective methods. The addition of
	// ProtoReflect removes that need.

	typesByName         typesByName
	extensionsByMessage extensionsByMessage
}

type (
	typesByName         map[protoreflect.FullName]Type
	extensionsByMessage map[protoreflect.FullName]extensionsByNumber
	extensionsByNumber  map[protoreflect.FieldNumber]protoreflect.ExtensionType
)

// NewTypes returns a registry initialized with the provided set of types.
// If there are conflicts, the first one takes precedence.
func NewTypes(typs ...Type) *Types {
	// TODO: Allow setting resolver and parent via constructor?
	r := new(Types)
	r.Register(typs...) // ignore errors; first takes precedence
	return r
}

// Register registers the provided list of descriptor types.
//
// If a registration conflict occurs for enum, message, or extension types
// (e.g., two different types have the same full name),
// then the first type takes precedence and an error is returned.
func (r *Types) Register(typs ...Type) error {
	var firstErr error
typeLoop:
	for _, typ := range typs {
		switch typ.(type) {
		case protoreflect.EnumType, protoreflect.MessageType, protoreflect.ExtensionType:
			// Check for conflicts in typesByName.
			name := typ.FullName()
			if r.typesByName[name] != nil {
				if firstErr == nil {
					firstErr = errors.New("%v %v is already registered", typeName(typ), name)
				}
				continue typeLoop
			}

			// Check for conflicts in extensionsByMessage.
			if xt, _ := typ.(protoreflect.ExtensionType); xt != nil {
				field := xt.Number()
				message := xt.ExtendedType().FullName()
				if r.extensionsByMessage[message][field] != nil {
					if firstErr == nil {
						firstErr = errors.New("extension %v is already registered on message %v", name, message)
					}
					continue typeLoop
				}

				// Update extensionsByMessage.
				if r.extensionsByMessage == nil {
					r.extensionsByMessage = make(extensionsByMessage)
				}
				if r.extensionsByMessage[message] == nil {
					r.extensionsByMessage[message] = make(extensionsByNumber)
				}
				r.extensionsByMessage[message][field] = xt
			}

			// Update typesByName.
			if r.typesByName == nil {
				r.typesByName = make(typesByName)
			}
			r.typesByName[name] = typ
		default:
			if firstErr == nil {
				firstErr = errors.New("invalid type: %v", typeName(typ))
			}
		}
	}
	return firstErr
}

// FindEnumByName looks up an enum by its full name.
// E.g., "google.protobuf.Field.Kind".
//
// This returns (nil, NotFound) if not found.
func (r *Types) FindEnumByName(enum protoreflect.FullName) (protoreflect.EnumType, error) {
	r.globalCheck()
	if r == nil {
		return nil, NotFound
	}
	v, _ := r.typesByName[enum]
	if v == nil && r.Resolver != nil {
		var err error
		v, err = r.Resolver(string(enum))
		if err != nil && err != NotFound {
			return nil, err
		}
	}
	if v != nil {
		if et, _ := v.(protoreflect.EnumType); et != nil {
			return et, nil
		}
		return nil, errors.New("found wrong type: got %v, want enum", typeName(v))
	}
	return r.Parent.FindEnumByName(enum)
}

// FindMessageByName looks up a message by its full name.
// E.g., "google.protobuf.Any"
//
// This return (nil, NotFound) if not found.
func (r *Types) FindMessageByName(message protoreflect.FullName) (protoreflect.MessageType, error) {
	// The full name by itself is a valid URL.
	return r.FindMessageByURL(string(message))
}

// FindMessageByURL looks up a message by a URL identifier.
// See Resolver for the format of the URL.
//
// This returns (nil, NotFound) if not found.
func (r *Types) FindMessageByURL(url string) (protoreflect.MessageType, error) {
	r.globalCheck()
	if r == nil {
		return nil, NotFound
	}
	message := protoreflect.FullName(url)
	if i := strings.LastIndexByte(url, '/'); i >= 0 {
		message = message[i+len("/"):]
	}

	v, _ := r.typesByName[message]
	if v == nil && r.Resolver != nil {
		var err error
		v, err = r.Resolver(url)
		if err != nil && err != NotFound {
			return nil, err
		}
	}
	if v != nil {
		if mt, _ := v.(protoreflect.MessageType); mt != nil {
			return mt, nil
		}
		return nil, errors.New("found wrong type: got %v, want message", typeName(v))
	}
	return r.Parent.FindMessageByURL(url)
}

// FindExtensionByName looks up a extension field by the field's full name.
// Note that this is the full name of the field as determined by
// where the extension is declared and is unrelated to the full name of the
// message being extended.
//
// This returns (nil, NotFound) if not found.
func (r *Types) FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error) {
	r.globalCheck()
	if r == nil {
		return nil, NotFound
	}
	v, _ := r.typesByName[field]
	if v == nil && r.Resolver != nil {
		var err error
		v, err = r.Resolver(string(field))
		if err != nil && err != NotFound {
			return nil, err
		}
	}
	if v != nil {
		if xt, _ := v.(protoreflect.ExtensionType); xt != nil {
			return xt, nil
		}
		return nil, errors.New("found wrong type: got %v, want extension", typeName(v))
	}
	return r.Parent.FindExtensionByName(field)
}

// FindExtensionByNumber looks up a extension field by the field number
// within some parent message, identified by full name.
//
// This returns (nil, NotFound) if not found.
func (r *Types) FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error) {
	r.globalCheck()
	if r == nil {
		return nil, NotFound
	}
	if xt, ok := r.extensionsByMessage[message][field]; ok {
		return xt, nil
	}
	return r.Parent.FindExtensionByNumber(message, field)
}

// RangeEnums iterates over all registered enums.
// Iteration order is undefined.
func (r *Types) RangeEnums(f func(protoreflect.EnumType) bool) {
	r.globalCheck()
	if r == nil {
		return
	}
	for _, typ := range r.typesByName {
		if et, ok := typ.(protoreflect.EnumType); ok {
			if !f(et) {
				return
			}
		}
	}
	r.Parent.RangeEnums(f)
}

// RangeMessages iterates over all registered messages.
// Iteration order is undefined.
func (r *Types) RangeMessages(f func(protoreflect.MessageType) bool) {
	r.globalCheck()
	if r == nil {
		return
	}
	for _, typ := range r.typesByName {
		if mt, ok := typ.(protoreflect.MessageType); ok {
			if !f(mt) {
				return
			}
		}
	}
	r.Parent.RangeMessages(f)
}

// RangeExtensions iterates over all registered extensions.
// Iteration order is undefined.
func (r *Types) RangeExtensions(f func(protoreflect.ExtensionType) bool) {
	r.globalCheck()
	if r == nil {
		return
	}
	for _, typ := range r.typesByName {
		if xt, ok := typ.(protoreflect.ExtensionType); ok {
			if !f(xt) {
				return
			}
		}
	}
	r.Parent.RangeExtensions(f)
}

// RangeExtensionsByMessage iterates over all registered extensions filtered
// by a given message type. Iteration order is undefined.
func (r *Types) RangeExtensionsByMessage(message protoreflect.FullName, f func(protoreflect.ExtensionType) bool) {
	r.globalCheck()
	if r == nil {
		return
	}
	for _, xt := range r.extensionsByMessage[message] {
		if !f(xt) {
			return
		}
	}
	r.Parent.RangeExtensionsByMessage(message, f)
}

func (r *Types) globalCheck() {
	if r == GlobalTypes && (r.Parent != nil || r.Resolver != nil) {
		panic("GlobalTypes.Parent and GlobalTypes.Resolver cannot be set")
	}
}

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