// 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 proto

import (
	"google.golang.org/protobuf/internal/encoding/wire"
	"google.golang.org/protobuf/internal/errors"
	"google.golang.org/protobuf/internal/pragma"
	"google.golang.org/protobuf/reflect/protoreflect"
	"google.golang.org/protobuf/reflect/protoregistry"
	"google.golang.org/protobuf/runtime/protoiface"
)

// UnmarshalOptions configures the unmarshaler.
//
// Example usage:
//   err := UnmarshalOptions{DiscardUnknown: true}.Unmarshal(b, m)
type UnmarshalOptions struct {
	// AllowPartial accepts input for messages that will result in missing
	// required fields. If AllowPartial is false (the default), Unmarshal will
	// return an error if there are any missing required fields.
	AllowPartial bool

	// If DiscardUnknown is set, unknown fields are ignored.
	DiscardUnknown bool

	// Resolver is used for looking up types when unmarshaling extension fields.
	// If nil, this defaults to using protoregistry.GlobalTypes.
	Resolver *protoregistry.Types

	pragma.NoUnkeyedLiterals
}

var _ = protoiface.UnmarshalOptions(UnmarshalOptions{})

// Unmarshal parses the wire-format message in b and places the result in m.
func Unmarshal(b []byte, m Message) error {
	return UnmarshalOptions{}.Unmarshal(b, m)
}

// Unmarshal parses the wire-format message in b and places the result in m.
func (o UnmarshalOptions) Unmarshal(b []byte, m Message) error {
	if o.Resolver == nil {
		o.Resolver = protoregistry.GlobalTypes
	}

	// TODO: Reset m?
	err := o.unmarshalMessageFast(b, m)
	if err == errInternalNoFast {
		err = o.unmarshalMessage(b, m.ProtoReflect())
	}
	var nerr errors.NonFatal
	if !nerr.Merge(err) {
		return err
	}
	if !o.AllowPartial {
		nerr.Merge(IsInitialized(m))
	}
	return nerr.E
}

func (o UnmarshalOptions) unmarshalMessageFast(b []byte, m Message) error {
	methods := protoMethods(m)
	if methods == nil || methods.Unmarshal == nil {
		return errInternalNoFast
	}
	return methods.Unmarshal(b, m, protoiface.UnmarshalOptions(o))
}

func (o UnmarshalOptions) unmarshalMessage(b []byte, m protoreflect.Message) error {
	messageDesc := m.Descriptor()
	fieldDescs := messageDesc.Fields()
	knownFields := m.KnownFields()
	unknownFields := m.UnknownFields()
	var nerr errors.NonFatal
	for len(b) > 0 {
		// Parse the tag (field number and wire type).
		num, wtyp, tagLen := wire.ConsumeTag(b)
		if tagLen < 0 {
			return wire.ParseError(tagLen)
		}

		// Parse the field value.
		fieldDesc := fieldDescs.ByNumber(num)
		if fieldDesc == nil {
			extType := knownFields.ExtensionTypes().ByNumber(num)
			if extType == nil && messageDesc.ExtensionRanges().Has(num) {
				var err error
				extType, err = o.Resolver.FindExtensionByNumber(messageDesc.FullName(), num)
				if err != nil && err != protoregistry.NotFound {
					return err
				}
				if extType != nil {
					knownFields.ExtensionTypes().Register(extType)
				}
			}
			if extType != nil {
				fieldDesc = extType.Descriptor()
			}
		}
		var err error
		var valLen int
		switch {
		case fieldDesc == nil:
			err = errUnknown
		case fieldDesc.IsList():
			valLen, err = o.unmarshalList(b[tagLen:], wtyp, num, knownFields.Get(num).List(), fieldDesc)
		case fieldDesc.IsMap():
			valLen, err = o.unmarshalMap(b[tagLen:], wtyp, num, knownFields.Get(num).Map(), fieldDesc)
		default:
			valLen, err = o.unmarshalScalarField(b[tagLen:], wtyp, num, knownFields, fieldDesc)
		}
		if err == errUnknown {
			valLen = wire.ConsumeFieldValue(num, wtyp, b[tagLen:])
			if valLen < 0 {
				return wire.ParseError(valLen)
			}
			unknownFields.Set(num, append(unknownFields.Get(num), b[:tagLen+valLen]...))
		} else if !nerr.Merge(err) {
			return err
		}
		b = b[tagLen+valLen:]
	}
	return nerr.E
}

func (o UnmarshalOptions) unmarshalScalarField(b []byte, wtyp wire.Type, num wire.Number, knownFields protoreflect.KnownFields, field protoreflect.FieldDescriptor) (n int, err error) {
	var nerr errors.NonFatal
	v, n, err := o.unmarshalScalar(b, wtyp, num, field)
	if !nerr.Merge(err) {
		return 0, err
	}
	switch field.Kind() {
	case protoreflect.GroupKind, protoreflect.MessageKind:
		// Messages are merged with any existing message value,
		// unless the message is part of a oneof.
		//
		// TODO: C++ merges into oneofs, while v1 does not.
		// Evaluate which behavior to pick.
		var m protoreflect.Message
		if knownFields.Has(num) && field.ContainingOneof() == nil {
			m = knownFields.Get(num).Message()
		} else {
			m = knownFields.NewMessage(num)
			knownFields.Set(num, protoreflect.ValueOf(m))
		}
		// Pass up errors (fatal and otherwise).
		if err := o.unmarshalMessage(v.Bytes(), m); !nerr.Merge(err) {
			return n, err
		}
	default:
		// Non-message scalars replace the previous value.
		knownFields.Set(num, v)
	}
	return n, nerr.E
}

func (o UnmarshalOptions) unmarshalMap(b []byte, wtyp wire.Type, num wire.Number, mapv protoreflect.Map, field protoreflect.FieldDescriptor) (n int, err error) {
	if wtyp != wire.BytesType {
		return 0, errUnknown
	}
	b, n = wire.ConsumeBytes(b)
	if n < 0 {
		return 0, wire.ParseError(n)
	}
	var (
		keyField = field.MapKey()
		valField = field.MapValue()
		key      protoreflect.Value
		val      protoreflect.Value
		haveKey  bool
		haveVal  bool
	)
	switch valField.Kind() {
	case protoreflect.GroupKind, protoreflect.MessageKind:
		val = protoreflect.ValueOf(mapv.NewMessage())
	}
	// Map entries are represented as a two-element message with fields
	// containing the key and value.
	var nerr errors.NonFatal
	for len(b) > 0 {
		num, wtyp, n := wire.ConsumeTag(b)
		if n < 0 {
			return 0, wire.ParseError(n)
		}
		b = b[n:]
		err = errUnknown
		switch num {
		case 1:
			key, n, err = o.unmarshalScalar(b, wtyp, num, keyField)
			if !nerr.Merge(err) {
				break
			}
			err = nil
			haveKey = true
		case 2:
			var v protoreflect.Value
			v, n, err = o.unmarshalScalar(b, wtyp, num, valField)
			if !nerr.Merge(err) {
				break
			}
			err = nil
			switch valField.Kind() {
			case protoreflect.GroupKind, protoreflect.MessageKind:
				if err := o.unmarshalMessage(v.Bytes(), val.Message()); !nerr.Merge(err) {
					return 0, err
				}
			default:
				val = v
			}
			haveVal = true
		}
		if err == errUnknown {
			n = wire.ConsumeFieldValue(num, wtyp, b)
			if n < 0 {
				return 0, wire.ParseError(n)
			}
		} else if err != nil {
			return 0, err
		}
		b = b[n:]
	}
	// Every map entry should have entries for key and value, but this is not strictly required.
	if !haveKey {
		key = keyField.Default()
	}
	if !haveVal {
		switch valField.Kind() {
		case protoreflect.GroupKind, protoreflect.MessageKind:
		default:
			val = valField.Default()
		}
	}
	mapv.Set(key.MapKey(), val)
	return n, nerr.E
}

// errUnknown is used internally to indicate fields which should be added
// to the unknown field set of a message. It is never returned from an exported
// function.
var errUnknown = errors.New("BUG: internal error (unknown)")
