package com.atlassian.bitbucket.mesh.git.builder.catfile;

import com.atlassian.bitbucket.mesh.git.GitObjectInfo;
import com.atlassian.bitbucket.mesh.git.GitObjectType;
import com.atlassian.bitbucket.mesh.process.OsProcess;
import com.google.common.collect.ImmutableList;
import org.apache.commons.lang3.mutable.MutableBoolean;
import org.hamcrest.collection.IsIterableContainingInOrder;
import org.junit.Test;

import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;

public class InfoBatchCheckCatFilesStdioHandlerTest {

    @Test
    public void testHandlerInput() {
        List<String> ids = ImmutableList.of("2e10dd2d1d5eea9291b296e78312e8a703964a95",
                "2e10dd2d1d5eea9291b296e78312e8a703964a95:some_path");

        MutableBoolean closed = new MutableBoolean();

        OsProcess process = mock(OsProcess.class);
        doAnswer(invocation -> {
            closed.setTrue();

            return null;
        }).when(process).closeStdin(anyBoolean());

        InfoBatchCheckCatFilesStdioHandler handler = new InfoBatchCheckCatFilesStdioHandler(ids);
        handler.onPreStart(process);
        handler.onStart(process);

        List<String> requested = new ArrayList<>();
        ByteBuffer stdin = ByteBuffer.allocate(100);
        while (true) {
            handler.onStdinReady(stdin);
            if (closed.isTrue()) {
                //The handler has requested as many commits as it wants to
                break;
            }

            requested.add(new String(stdin.array(), stdin.arrayOffset(), stdin.remaining() - 1)); //Drop the newline
            stdin.clear();

            if (requested.size() > 1) {
                continue;
            }

            //For the first requested object, provide some object details
            CharBuffer output = CharBuffer.wrap("09dff955444dde6bd37548332f8b82ab46ddd7b0 commit 123");
            ByteBuffer buffer = ByteBuffer.allocate(100);
            CharsetEncoder encoder = UTF_8.newEncoder();
            CoderResult result;
            do {
                result = encoder.encode(output, buffer, true);
                buffer.flip();

                handler.onStdout(buffer, result.isUnderflow());
                buffer.compact();
            } while (result.isOverflow());
        }

        handler.onExit(0);

        assertThat(requested, IsIterableContainingInOrder.contains(ids.toArray(new String[0])));

        Map<String, GitObjectInfo> objects = handler.getResult();
        assertEquals(1, objects.size());
        GitObjectInfo objectInfo = objects.get("2e10dd2d1d5eea9291b296e78312e8a703964a95");
        assertNotNull(objectInfo);
        assertEquals("09dff955444dde6bd37548332f8b82ab46ddd7b0", objectInfo.getObjectId());
        assertEquals(GitObjectType.COMMIT, objectInfo.getType());
        assertEquals(123L, objectInfo.getSize());
    }
}
