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

import (
	"testing"

	"google.golang.org/protobuf/internal/encoding/pack"
	"google.golang.org/protobuf/internal/flags"
	"google.golang.org/protobuf/internal/protobuild"
	"google.golang.org/protobuf/proto"

	testpb "google.golang.org/protobuf/internal/testprotos/test"
	weakpb "google.golang.org/protobuf/internal/testprotos/test/weak1"
)

func init() {
	if flags.ProtoLegacy {
		testValidMessages = append(testValidMessages, testWeakValidMessages...)
		testInvalidMessages = append(testInvalidMessages, testWeakInvalidMessages...)
		testMerges = append(testMerges, testWeakMerges...)
	}
}

var testWeakValidMessages = []testProto{
	{
		desc: "weak message",
		decodeTo: []proto.Message{
			func() proto.Message {
				if !flags.ProtoLegacy {
					return nil
				}
				m := &testpb.TestWeak{}
				m.SetWeakMessage1(&weakpb.WeakImportMessage1{
					A: proto.Int32(1000),
				})
				m.ProtoReflect().SetUnknown(pack.Message{
					pack.Tag{2, pack.BytesType}, pack.LengthPrefix(pack.Message{
						pack.Tag{1, pack.VarintType}, pack.Varint(2000),
					}),
				}.Marshal())
				return m
			}(),
		},
		wire: pack.Message{
			pack.Tag{1, pack.BytesType}, pack.LengthPrefix(pack.Message{
				pack.Tag{1, pack.VarintType}, pack.Varint(1000),
			}),
			pack.Tag{2, pack.BytesType}, pack.LengthPrefix(pack.Message{
				pack.Tag{1, pack.VarintType}, pack.Varint(2000),
			}),
		}.Marshal(),
	},
}

var testWeakInvalidMessages = []testProto{
	{
		desc:     "invalid field number 0 in weak message",
		decodeTo: []proto.Message{(*testpb.TestWeak)(nil)},
		wire: pack.Message{
			pack.Tag{1, pack.BytesType}, pack.LengthPrefix(pack.Message{
				pack.Tag{0, pack.VarintType}, pack.Varint(1000),
			}),
		}.Marshal(),
	},
}

var testWeakMerges = []testMerge{
	{
		desc: "clone weak message",
		src: protobuild.Message{
			"weak_message1": protobuild.Message{
				"a": 1,
			},
		},
		types: []proto.Message{&testpb.TestWeak{}},
	}, {
		desc: "merge weak message",
		dst: protobuild.Message{
			"weak_message1": protobuild.Message{
				"a": 1,
			},
		},
		src: protobuild.Message{
			"weak_message1": protobuild.Message{
				"a": 2,
			},
		},
		want: protobuild.Message{
			"weak_message1": protobuild.Message{
				"a": 2,
			},
		},
		types: []proto.Message{&testpb.TestWeak{}},
	},
}

func TestWeakNil(t *testing.T) {
	if !flags.ProtoLegacy {
		t.SkipNow()
	}

	m := new(testpb.TestWeak)
	if v, ok := m.GetWeakMessage1().(*weakpb.WeakImportMessage1); !ok || v != nil {
		t.Errorf("m.GetWeakMessage1() = type %[1]T(%[1]v), want (*weakpb.WeakImportMessage1)", v)
	}
}

func TestWeakMarshalNil(t *testing.T) {
	if !flags.ProtoLegacy {
		t.SkipNow()
	}

	m := new(testpb.TestWeak)
	m.SetWeakMessage1(nil)
	if b, err := proto.Marshal(m); err != nil || len(b) != 0 {
		t.Errorf("Marshal(weak field set to nil) = [%x], %v; want [], nil", b, err)
	}
	m.SetWeakMessage1((*weakpb.WeakImportMessage1)(nil))
	if b, err := proto.Marshal(m); err != nil || len(b) != 0 {
		t.Errorf("Marshal(weak field set to typed nil) = [%x], %v; want [], nil", b, err)
	}
}
