package com.atlassian.bitbucket.mesh.git.hosting;

import com.google.common.base.Charsets;
import org.junit.Test;

import java.io.ByteArrayInputStream;
import java.io.IOException;

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.*;

public class GitPacketsTest {

    @Test
    public void testGetFlush() {
        byte[] flush = GitPackets.getFlush();
        assertEquals("0000", new String(flush, UTF_8));

        // check that we got a copy
        flush[0] = '1';
        assertEquals("0000", new String(GitPackets.getFlush(), UTF_8));
    }

    @Test
    public void testIsDelim() {
        assertTrue(GitPackets.isDelim("0001".getBytes(UTF_8)));
        assertTrue(GitPackets.isDelim(GitPackets.getDelim()));
        assertFalse(GitPackets.isDelim("0000".getBytes(UTF_8)));
        assertFalse(GitPackets.isDelim(null));
    }

    @Test
    public void testIsDone() {
        assertTrue(GitPackets.isDone("0009done\n".getBytes(UTF_8)));
        assertTrue(GitPackets.isDone("0008done".getBytes(UTF_8)));
        assertFalse(GitPackets.isDone("000fdonerkebab\n".getBytes(UTF_8)));
        assertFalse(GitPackets.isDone(null));
    }

    @Test
    public void testIsFlush() {
        assertTrue(GitPackets.isFlush("0000".getBytes(UTF_8)));
        assertFalse(GitPackets.isFlush("00000".getBytes(UTF_8)));
        assertFalse(GitPackets.isFlush(null));
    }

    @Test
    public void testReadPacket() throws IOException {
        String example = "001e# service=git-upload-pack\n" +
                "000000a33d36b3a45440d4d6d26f941225ded5376dadbf29 HEAD\0multi_ack thin-pack side-band side-band-64k " +
                "ofs-delta shallow no-progress include-tag multi_ack_detailed no-done\n" +
                "003c4f4cfe40875a88985e048c31feb1fc9648f1966c refs/heads/1.3\n" +
                "005b3e9f686ccf249d3199fcedee30989084625e106b refs/heads/1.3-STASHDEV-2001-mheemskerk-oauth\n" +
                "0001" +
                "0000";

        ByteArrayInputStream bis = new ByteArrayInputStream(example.getBytes(Charsets.UTF_8));

        assertPacket("001e# service=git-upload-pack\n", GitPackets.readPacket(bis));
        assertPacket("0000", GitPackets.readPacket(bis));
        assertPacket("00a33d36b3a45440d4d6d26f941225ded5376dadbf29 HEAD\0multi_ack thin-pack side-band side-band-64k " +
                "ofs-delta shallow no-progress include-tag multi_ack_detailed no-done\n", GitPackets.readPacket(bis));
        assertPacket("003c4f4cfe40875a88985e048c31feb1fc9648f1966c refs/heads/1.3\n", GitPackets.readPacket(bis));
        assertPacket("005b3e9f686ccf249d3199fcedee30989084625e106b refs/heads/1.3-STASHDEV-2001-mheemskerk-oauth\n",
                GitPackets.readPacket(bis));
        assertPacket("0001", GitPackets.readPacket(bis));
        assertPacket("0000", GitPackets.readPacket(bis));
    }

    @Test(expected = IOException.class)
    public void testReadPacketNonPacketStream() throws IOException {
        String example = "This is not a packet stream";

        ByteArrayInputStream bis = new ByteArrayInputStream(example.getBytes(Charsets.UTF_8));
        GitPackets.readPacket(bis);
    }

    @Test(expected = IOException.class)
    public void testReadPacketUnexpectedEOF() throws IOException {
        String example = "001e# service=git-"; // truncated

        ByteArrayInputStream bis = new ByteArrayInputStream(example.getBytes(Charsets.UTF_8));
        GitPackets.readPacket(bis);
    }

    @Test(expected = IllegalArgumentException.class)
    public void testToLineNull() {
        GitPackets.toLine(null);
    }

    @Test
    public void testToLineFromDelimPacket() {
        assertEquals("", GitPackets.toLine("0001".getBytes(UTF_8)));
    }

    @Test
    public void testToLineFromFlushPacket() {
        assertEquals("", GitPackets.toLine("0000".getBytes(UTF_8)));
    }

    @Test
    public void testToLineFromPacket() {
        assertEquals("done\n", GitPackets.toLine("0009done\n".getBytes(UTF_8)));
    }

    @Test(expected = IllegalArgumentException.class)
    public void testToLineFromTooShortPacket() {
        GitPackets.toLine("00".getBytes(UTF_8));
    }

    private static void assertPacket(String expectedPacket, byte[] packet) {
        assertNotNull("Packet should not be null", packet);

        String actualPacket = new String(packet, Charsets.UTF_8);
        assertEquals(expectedPacket, actualPacket);
    }
}
