package com.atlassian.stash.internal.hook;

import com.google.common.base.Charsets;
import com.google.common.collect.Lists;
import org.junit.Ignore;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.List;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

@Ignore
class SocketTransferInputTestDataBuilder {

    private final List<SocketTransferInput.Chunk> chunks = Lists.newArrayList();

    public SocketTransferInputTestDataBuilder addChunk(SocketTransferInput.ChunkType type, String data) throws IOException {
        chunks.add(new SocketTransferInput.Chunk(type, data));
        return this;
    }

    public SocketTransferInput build() throws IOException {
        SocketTransferInput mock = mock(SocketTransferInput.class);
        final Iterator<SocketTransferInput.Chunk> it = chunks.iterator();
        when(mock.readChunk()).thenAnswer(new Answer<SocketTransferInput.Chunk>() {
            @Override
            public SocketTransferInput.Chunk answer(InvocationOnMock invocationOnMock) throws Throwable {
                if (!it.hasNext()) {
                    throw new EOFException();
                }
                return it.next();
            }
        });
        when(mock.readRequestId()).thenCallRealMethod();
        when(mock.readHookType()).thenCallRealMethod();
        return mock;
    }

    public InputStream buildInputStream() throws IOException {
        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
        DataOutputStream out = new DataOutputStream(bytes);
        for (SocketTransferInput.Chunk chunk : chunks) {
            out.write(Charsets.US_ASCII.encode(String.valueOf(chunk.getType().getCharacter())).array());
            if (chunk.getValue() != null) {
                String value = chunk.getValue();
                byte[] valueBytes = value.getBytes(StandardCharsets.UTF_8);
                out.writeShort(valueBytes.length);
                out.write(valueBytes);
            }
        }
        return new ByteArrayInputStream(bytes.toByteArray());
    }

    public void replayAndVerify() throws IOException {
        InputStream in = buildInputStream();
        SocketTransferInput input = new SocketTransferInput(in);
        for (SocketTransferInput.Chunk expected : chunks) {
            SocketTransferInputTest.assertChunk(input.readChunk(), expected.getType(), expected.getValue());
        }
        assertEquals("There should be no more bytes available", 0, in.available());
    }

}
