package proto

import (
	"bytes"
	"testing"
)

var (
	keyint = 12
	bint8  = []byte{0x0c}
	bint64 = []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c}

	keystr = "Ash nazg durbatulûk, ash nazg gimbatul, ash nazg thrakatulûk, agh burzum-ishi krimpatul" // google LOTR one ring
	bstr   = []byte{0x00, 0x59, 0x41, 0x73, 0x68, 0x20, 0x6e, 0x61, 0x7a, 0x67, 0x20, 0x64, 0x75, 0x72, 0x62, 0x61, 0x74, 0x75, 0x6c, 0xc3, 0xbb, 0x6b, 0x2c, 0x20, 0x61, 0x73, 0x68, 0x20, 0x6e, 0x61, 0x7a, 0x67, 0x20, 0x67, 0x69, 0x6d, 0x62, 0x61, 0x74, 0x75, 0x6c, 0x2c, 0x20, 0x61, 0x73, 0x68, 0x20, 0x6e, 0x61, 0x7a, 0x67, 0x20, 0x74, 0x68, 0x72, 0x61, 0x6b, 0x61, 0x74, 0x75, 0x6c, 0xc3, 0xbb, 0x6b, 0x2c, 0x20, 0x61, 0x67, 0x68, 0x20, 0x62, 0x75, 0x72, 0x7a, 0x75, 0x6d, 0x2d, 0x69, 0x73, 0x68, 0x69, 0x20, 0x6b, 0x72, 0x69, 0x6d, 0x70, 0x61, 0x74, 0x75, 0x6c}
	bbyte  = []byte{0x00, 0x00, 0x00, 0x59, 0x41, 0x73, 0x68, 0x20, 0x6e, 0x61, 0x7a, 0x67, 0x20, 0x64, 0x75, 0x72, 0x62, 0x61, 0x74, 0x75, 0x6c, 0xc3, 0xbb, 0x6b, 0x2c, 0x20, 0x61, 0x73, 0x68, 0x20, 0x6e, 0x61, 0x7a, 0x67, 0x20, 0x67, 0x69, 0x6d, 0x62, 0x61, 0x74, 0x75, 0x6c, 0x2c, 0x20, 0x61, 0x73, 0x68, 0x20, 0x6e, 0x61, 0x7a, 0x67, 0x20, 0x74, 0x68, 0x72, 0x61, 0x6b, 0x61, 0x74, 0x75, 0x6c, 0xc3, 0xbb, 0x6b, 0x2c, 0x20, 0x61, 0x67, 0x68, 0x20, 0x62, 0x75, 0x72, 0x7a, 0x75, 0x6d, 0x2d, 0x69, 0x73, 0x68, 0x69, 0x20, 0x6b, 0x72, 0x69, 0x6d, 0x70, 0x61, 0x74, 0x75, 0x6c}
)

var b = bytes.NewBuffer(nil)

func getTestEncoder() *encoder {
	b.Reset()
	return NewEncoder(b)
}

func TestEncoder(t *testing.T) {
	e := getTestEncoder()
	e.EncodeInt8(int8(keyint))
	if !bytes.Equal(b.Bytes(), bint8) {
		t.Fatalf("bytes are not the same % x != % x", b.Bytes(), bint8)
	}

	e = getTestEncoder()
	e.EncodeInt64(int64(keyint))
	if !bytes.Equal(b.Bytes(), bint64) {
		t.Fatalf("bytes are not the same % x != % x", b.Bytes(), bint64)
	}

	e = getTestEncoder()
	e.EncodeString(string(keystr))
	if !bytes.Equal(b.Bytes(), bstr) {
		t.Fatalf("bytes are not the same % x != % x", b.Bytes(), bstr)
	}
}

func TestDecoder(t *testing.T) {
	d := NewDecoder(bytes.NewBuffer(bint8))
	if d.DecodeInt8() != int8(keyint) {
		t.Fatalf("int8 decoding failed")
	}

	d = NewDecoder(bytes.NewBuffer(bint64))
	if d.DecodeInt64() != int64(keyint) {
		t.Fatalf("int64 decoding failed")
	}

	d = NewDecoder(bytes.NewBuffer(bstr))
	if d.DecodeString() != keystr {
		t.Fatalf("string decoding failed")
	}

	d = NewDecoder(bytes.NewBuffer(bbyte))
	if !bytes.Equal(d.DecodeBytes(), []byte(keystr)) {
		t.Fatalf("bytes are not the same")
	}
}

func BenchmarkReadVarint(b *testing.B) {
	data := []byte{0x10}
	r := bytes.NewReader(data)
	dec := NewDecoder(r)

	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		r.Reset(data)
		x := dec.DecodeVarInt()
		if x != 8 {
			b.Fatalf("unexpected value decoded: %d", x)
		}
	}
}
