package serialize

import (
	"bytes"
	"reflect"
	"testing"

	"code.justin.tv/rhys/nursery/serialize/capnmsg"
	"github.com/glycerine/go-capnproto"
)

func TestCapnpRecode(t *testing.T) {
	seg1 := capn.NewBuffer(nil)

	start := capnmsg.NewRootMsg(seg1)
	err := toCapnp(&start, golden)
	if err != nil {
		t.Fatalf("convert: %v", err)
	}

	var buf1 bytes.Buffer
	_, err = seg1.WriteTo(&buf1)
	if err != nil {
		t.Fatalf("marshal: %v", err)
	}
	t.Logf("len: %d", buf1.Len())

	var buf2 bytes.Buffer
	seg2, err := capn.ReadFromStream(bytes.NewReader(buf1.Bytes()), &buf2)
	if err != nil {
		t.Fatalf("unmarshal: %v", err)
	}
	end := capnmsg.ReadRootMsg(seg2)

	silver := new(talGolden)
	err = fromCapnp(silver, &end)
	if err != nil {
		t.Fatalf("deconvert: %v", err)
	}

	if have, want := silver, golden; !reflect.DeepEqual(have, want) {
		t.Errorf("values don't match:\n%#v\n!=\n%#v", have, want)
	}
}

func BenchmarkCapnpEncode(b *testing.B) {
	for i := 0; i < b.N; i++ {
		seg1 := capn.NewBuffer(nil)

		start := capnmsg.NewRootMsg(seg1)
		err := toCapnp(&start, golden)
		if err != nil {
			b.Fatalf("convert: %v", err)
		}

		var buf1 bytes.Buffer
		_, err = seg1.WriteTo(&buf1)
		if err != nil {
			b.Fatalf("marshal: %v", err)
		}
		if i == 0 {
			b.SetBytes(int64(buf1.Len()))
		}
	}
}

func BenchmarkCapnpDecode(b *testing.B) {
	seg1 := capn.NewBuffer(nil)

	start := capnmsg.NewRootMsg(seg1)
	err := toCapnp(&start, golden)
	if err != nil {
		b.Fatalf("convert: %v", err)
	}

	var buf1 bytes.Buffer
	_, err = seg1.WriteTo(&buf1)
	if err != nil {
		b.Fatalf("marshal: %v", err)
	}
	b.SetBytes(int64(buf1.Len()))

	for i := 0; i < b.N; i++ {
		var buf2 bytes.Buffer
		seg2, err := capn.ReadFromStream(bytes.NewReader(buf1.Bytes()), &buf2)
		if err != nil {
			b.Fatalf("unmarshal: %v", err)
		}
		end := capnmsg.ReadRootMsg(seg2)

		silver := new(talGolden)
		err = fromCapnp(silver, &end)
		if err != nil {
			b.Fatalf("deconvert: %v", err)
		}
	}
}

func BenchmarkCapnpDecodeTraceid(b *testing.B) {
	seg1 := capn.NewBuffer(nil)

	start := capnmsg.NewRootMsg(seg1)
	err := toCapnp(&start, golden)
	if err != nil {
		b.Fatalf("convert: %v", err)
	}

	var buf1 bytes.Buffer
	_, err = seg1.WriteTo(&buf1)
	if err != nil {
		b.Fatalf("marshal: %v", err)
	}
	b.SetBytes(int64(buf1.Len()))

	for i := 0; i < b.N; i++ {
		seg, _, err := capn.ReadFromMemoryZeroCopy(buf1.Bytes())
		if err != nil {
			b.Fatalf("unmarshal: %v", err)
		}
		end := capnmsg.ReadRootMsg(seg)
		if have, want := end.Traceid(), golden.TraceID; have != want {
			b.Fatalf("traceid; %d != %d", have, want)
		}
	}
}
