package wayland

import (
	"encoding/binary"
	"testing"
)

func TestPad4(t *testing.T) {
	cases := []struct {
		in   int
		want int
	}{
		{0, 0},
		{1, 4},
		{2, 4},
		{3, 4},
		{4, 4},
		{5, 8},
		{13, 16},
		{14, 16},
	}
	for _, tc := range cases {
		if got := pad4(tc.in); got != tc.want {
			t.Errorf("pad4(%d) = %d, want %d", tc.in, got, tc.want)
		}
	}
}

func TestEncodeDecodeString(t *testing.T) {
	s := "wl_compositor"
	enc := encodeString(s)

	strLen := binary.LittleEndian.Uint32(enc[:4])
	if strLen != 14 {
		t.Fatalf("strLen = %d, want 14", strLen)
	}

	if len(enc) != 20 {
		t.Fatalf("total encoded len = %d, want 20", len(enc))
	}

	if enc[17] != 0 {
		t.Errorf("expected NUL at byte 17, got %d", enc[17])
	}
	if enc[18] != 0 || enc[19] != 0 {
		t.Errorf("padding bytes non-zero: %d, %d", enc[18], enc[19])
	}

	dec, nextOff, err := decodeString(enc, 0)
	if err != nil {
		t.Fatalf("decodeString failed: %v", err)
	}
	if dec != s {
		t.Errorf("decoded %q != want %q", dec, s)
	}
	if nextOff != len(enc) {
		t.Errorf("nextOff %d != %d", nextOff, len(enc))
	}
}

func TestDecodeStringEdgeCases(t *testing.T) {
	// 1. Empty data
	if _, _, err := decodeString(nil, 0); err == nil {
		t.Error("expected error on empty data")
	}

	// 2. strLen == 0
	var buf0 [4]byte
	binary.LittleEndian.PutUint32(buf0[:], 0)
	s, off, err := decodeString(buf0[:], 0)
	if err != nil || s != "" || off != 4 {
		t.Errorf("strLen=0: got (%q, %d, %v), want empty", s, off, err)
	}

	// 3. strLen == 1 (just NUL)
	buf1 := []byte{1, 0, 0, 0, 0, 0, 0, 0}
	s1, off1, err1 := decodeString(buf1, 0)
	if err1 != nil || s1 != "" || off1 != 8 {
		t.Errorf("strLen=1: got (%q, %d, %v), want empty", s1, off1, err1)
	}

	// 4. Truncated payload
	bufTrunc := []byte{10, 0, 0, 0, 'a', 'b', 'c'}
	if _, _, err := decodeString(bufTrunc, 0); err == nil {
		t.Error("expected error on truncated payload")
	}
}
