// Copyright 2019 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 impl

import (
	"math"
	"sort"
	"sync/atomic"

	"google.golang.org/protobuf/internal/flags"
	proto "google.golang.org/protobuf/proto"
	piface "google.golang.org/protobuf/runtime/protoiface"
)

type marshalOptions struct {
	flags piface.MarshalInputFlags
}

func (o marshalOptions) Options() proto.MarshalOptions {
	return proto.MarshalOptions{
		AllowPartial:  true,
		Deterministic: o.Deterministic(),
		UseCachedSize: o.UseCachedSize(),
	}
}

func (o marshalOptions) Deterministic() bool { return o.flags&piface.MarshalDeterministic != 0 }
func (o marshalOptions) UseCachedSize() bool { return o.flags&piface.MarshalUseCachedSize != 0 }

// size is protoreflect.Methods.Size.
func (mi *MessageInfo) size(in piface.SizeInput) piface.SizeOutput {
	var p pointer
	if ms, ok := in.Message.(*messageState); ok {
		p = ms.pointer()
	} else {
		p = in.Message.(*messageReflectWrapper).pointer()
	}
	size := mi.sizePointer(p, marshalOptions{
		flags: in.Flags,
	})
	return piface.SizeOutput{Size: size}
}

func (mi *MessageInfo) sizePointer(p pointer, opts marshalOptions) (size int) {
	mi.init()
	if p.IsNil() {
		return 0
	}
	if opts.UseCachedSize() && mi.sizecacheOffset.IsValid() {
		// The size cache contains the size + 1, to allow the
		// zero value to be invalid, while also allowing for a
		// 0 size to be cached.
		if size := atomic.LoadInt32(p.Apply(mi.sizecacheOffset).Int32()); size > 0 {
			return int(size - 1)
		}
	}
	return mi.sizePointerSlow(p, opts)
}

func (mi *MessageInfo) sizePointerSlow(p pointer, opts marshalOptions) (size int) {
	if flags.ProtoLegacy && mi.isMessageSet {
		size = sizeMessageSet(mi, p, opts)
		if mi.sizecacheOffset.IsValid() {
			atomic.StoreInt32(p.Apply(mi.sizecacheOffset).Int32(), int32(size+1))
		}
		return size
	}
	if mi.extensionOffset.IsValid() {
		e := p.Apply(mi.extensionOffset).Extensions()
		size += mi.sizeExtensions(e, opts)
	}
	for _, f := range mi.orderedCoderFields {
		if f.funcs.size == nil {
			continue
		}
		fptr := p.Apply(f.offset)
		if f.isPointer && fptr.Elem().IsNil() {
			continue
		}
		size += f.funcs.size(fptr, f, opts)
	}
	if mi.unknownOffset.IsValid() {
		if u := mi.getUnknownBytes(p); u != nil {
			size += len(*u)
		}
	}
	if mi.sizecacheOffset.IsValid() {
		if size > (math.MaxInt32 - 1) {
			// The size is too large for the int32 sizecache field.
			// We will need to recompute the size when encoding;
			// unfortunately expensive, but better than invalid output.
			atomic.StoreInt32(p.Apply(mi.sizecacheOffset).Int32(), 0)
		} else {
			// The size cache contains the size + 1, to allow the
			// zero value to be invalid, while also allowing for a
			// 0 size to be cached.
			atomic.StoreInt32(p.Apply(mi.sizecacheOffset).Int32(), int32(size+1))
		}
	}
	return size
}

// marshal is protoreflect.Methods.Marshal.
func (mi *MessageInfo) marshal(in piface.MarshalInput) (out piface.MarshalOutput, err error) {
	var p pointer
	if ms, ok := in.Message.(*messageState); ok {
		p = ms.pointer()
	} else {
		p = in.Message.(*messageReflectWrapper).pointer()
	}
	b, err := mi.marshalAppendPointer(in.Buf, p, marshalOptions{
		flags: in.Flags,
	})
	return piface.MarshalOutput{Buf: b}, err
}

func (mi *MessageInfo) marshalAppendPointer(b []byte, p pointer, opts marshalOptions) ([]byte, error) {
	mi.init()
	if p.IsNil() {
		return b, nil
	}
	if flags.ProtoLegacy && mi.isMessageSet {
		return marshalMessageSet(mi, b, p, opts)
	}
	var err error
	// The old marshaler encodes extensions at beginning.
	if mi.extensionOffset.IsValid() {
		e := p.Apply(mi.extensionOffset).Extensions()
		// TODO: Special handling for MessageSet?
		b, err = mi.appendExtensions(b, e, opts)
		if err != nil {
			return b, err
		}
	}
	for _, f := range mi.orderedCoderFields {
		if f.funcs.marshal == nil {
			continue
		}
		fptr := p.Apply(f.offset)
		if f.isPointer && fptr.Elem().IsNil() {
			continue
		}
		b, err = f.funcs.marshal(b, fptr, f, opts)
		if err != nil {
			return b, err
		}
	}
	if mi.unknownOffset.IsValid() && !mi.isMessageSet {
		if u := mi.getUnknownBytes(p); u != nil {
			b = append(b, (*u)...)
		}
	}
	return b, nil
}

// fullyLazyExtensions returns true if we should attempt to keep extensions lazy over size and marshal.
func fullyLazyExtensions(opts marshalOptions) bool {
	// When deterministic marshaling is requested, force an unmarshal for lazy
	// extensions to produce a deterministic result, instead of passing through
	// bytes lazily that may or may not match what Go Protobuf would produce.
	return opts.flags&piface.MarshalDeterministic == 0
}

func (mi *MessageInfo) sizeExtensions(ext *map[int32]ExtensionField, opts marshalOptions) (n int) {
	if ext == nil {
		return 0
	}
	for _, x := range *ext {
		xi := getExtensionFieldInfo(x.Type())
		if xi.funcs.size == nil {
			continue
		}
		if fullyLazyExtensions(opts) {
			// Don't expand the extension, instead use the buffer to calculate size
			if lb := x.lazyBuffer(); lb != nil {
				// We got hold of the buffer, so it's still lazy.
				n += len(lb)
				continue
			}
		}
		n += xi.funcs.size(x.Value(), xi.tagsize, opts)
	}
	return n
}

func (mi *MessageInfo) appendExtensions(b []byte, ext *map[int32]ExtensionField, opts marshalOptions) ([]byte, error) {
	if ext == nil {
		return b, nil
	}

	switch len(*ext) {
	case 0:
		return b, nil
	case 1:
		// Fast-path for one extension: Don't bother sorting the keys.
		var err error
		for _, x := range *ext {
			xi := getExtensionFieldInfo(x.Type())
			if fullyLazyExtensions(opts) {
				// Don't expand the extension if it's still in wire format, instead use the buffer content.
				if lb := x.lazyBuffer(); lb != nil {
					b = append(b, lb...)
					continue
				}
			}
			b, err = xi.funcs.marshal(b, x.Value(), xi.wiretag, opts)
		}
		return b, err
	default:
		// Sort the keys to provide a deterministic encoding.
		// Not sure this is required, but the old code does it.
		keys := make([]int, 0, len(*ext))
		for k := range *ext {
			keys = append(keys, int(k))
		}
		sort.Ints(keys)
		var err error
		for _, k := range keys {
			x := (*ext)[int32(k)]
			xi := getExtensionFieldInfo(x.Type())
			if fullyLazyExtensions(opts) {
				// Don't expand the extension if it's still in wire format, instead use the buffer content.
				if lb := x.lazyBuffer(); lb != nil {
					b = append(b, lb...)
					continue
				}
			}
			b, err = xi.funcs.marshal(b, x.Value(), xi.wiretag, opts)
			if err != nil {
				return b, err
			}
		}
		return b, nil
	}
}
