package invalid.lena.scrcpy;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import org.junit.Test;

import java.io.ByteArrayInputStream;
import java.io.EOFException;

public class WireTest {

    @Test
    public void be32RoundTrip() {
        byte[] b = new byte[4];
        int[] cases = {0, 1, -1, 0x7fffffff, 0x80000000, 0x12345678};
        for (int v : cases) {
            Wire.writeBe32(b, 0, v);
            assertEquals(v, Wire.readBe32(b, 0));
        }
    }

    @Test
    public void be32Layout() {
        byte[] b = new byte[4];
        Wire.writeBe32(b, 0, 0x12345678);
        assertArrayEquals(new byte[]{0x12, 0x34, 0x56, 0x78}, b);
    }

    @Test
    public void be64RoundTrip() {
        byte[] b = new byte[8];
        long[] cases = {0L, 1L, -1L, Long.MAX_VALUE, Long.MIN_VALUE, 0x0123456789abcdefL};
        for (long v : cases) {
            Wire.writeBe64(b, 0, v);
            assertEquals(v, Wire.readBe64(b, 0));
        }
    }

    @Test
    public void le32RoundTrip() {
        byte[] b = new byte[4];
        int[] cases = {0, 1, -1, 0x7fffffff, 0x80000000, 0x12345678};
        for (int v : cases) {
            Wire.writeLe32(b, 0, v);
            assertEquals(v, Wire.readLe32(b, 0));
        }
    }

    @Test
    public void le32Layout() {
        byte[] b = new byte[4];
        Wire.writeLe32(b, 0, 0x12345678);
        assertArrayEquals(new byte[]{0x78, 0x56, 0x34, 0x12}, b);
    }

    @Test
    public void readFullyShortStreamThrows() throws Exception {
        ByteArrayInputStream in = new ByteArrayInputStream(new byte[3]);
        byte[] buf = new byte[8];
        try {
            Wire.readFully(in, buf);
            fail("expected EOFException");
        } catch (EOFException ignored) {
            // expected
        }
    }

    @Test
    public void fourccConstantsMatchScrcpy() {
        // Big-endian uint32 of the 4-char ASCII tag, NUL-padded on the LEFT
        // for short names (raw, aac) - mirrors AudioCodec / VideoCodec.
        assertEquals(0x68_32_36_34, Wire.CODEC_H264);  // "h264"
        assertEquals(0x68_32_36_35, Wire.CODEC_H265);  // "h265"
        assertEquals(0x61_76_30_31, Wire.CODEC_AV1);   // "av01"
        assertEquals(0x6f_70_75_73, Wire.CODEC_OPUS);  // "opus"
        assertEquals(0x66_6c_61_63, Wire.CODEC_FLAC);  // "flac"
        assertEquals(0x00_61_61_63, Wire.CODEC_AAC);   // "\0aac"
        assertEquals(0x00_72_61_77, Wire.CODEC_RAW);   // "\0raw"
    }

    @Test
    public void fourccName() {
        assertEquals("h264", Wire.fourccName(Wire.CODEC_H264));
        assertEquals("opus", Wire.fourccName(Wire.CODEC_OPUS));
    }

    @Test
    public void fourccNameTrimsLeadingNuls() {
        assertEquals("raw", Wire.fourccName(Wire.CODEC_RAW));
        assertEquals("aac", Wire.fourccName(Wire.CODEC_AAC));
    }
}
