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

import com.atlassian.bitbucket.mesh.AbstractWiredTest;
import com.atlassian.bitbucket.mesh.git.GitObjectInfo;
import com.atlassian.bitbucket.mesh.git.builder.GitProcessBuilderFactory;
import com.atlassian.bitbucket.mesh.repository.Repository;
import com.atlassian.bitbucket.mesh.test.annotation.Repo;
import org.junit.Test;

import javax.annotation.Resource;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import static com.atlassian.bitbucket.mesh.git.GitObjectType.*;
import static java.util.Optional.empty;
import static java.util.Optional.of;

public class InteractiveInfoBatchCheckCatFilesStdioHandlerTest extends AbstractWiredTest {

    private static final String BLOB_ID = "f49abb7d6c366e6f83470e36439bc162234d7963";
    private static final String COMMIT_ID = "ed69be6064dcef2d0b08b35192f581613e48411b";
    private static final String TREE_ID = "1ff86b241903dab46340611c450069ebdcaa3d2c";

    @Resource
    private GitProcessBuilderFactory builderFactory;
    @Repo
    private Repository repository;

    @Test(timeout = 2000L)
    public void testInteractiveHandling() throws Throwable {
        InteractiveInfoBatchCheckCatFilesStdioHandler handler = new InteractiveInfoBatchCheckCatFilesStdioHandler();
        Future<Void> future = builderFactory.builder(repository).catFile()
                .batchCheck()
                .build(handler)
                .start();
        try {
            assertEquals(empty(), handler.getInfo("missing"));
            assertEquals(of(new GitObjectInfo(COMMIT_ID, 262, COMMIT)), handler.getInfo(COMMIT_ID));
            assertEquals(of(new GitObjectInfo(BLOB_ID, 24, BLOB)), handler.getInfo(BLOB_ID));
            assertEquals(of(new GitObjectInfo(TREE_ID, 42, TREE)), handler.getInfo(TREE_ID));
        } finally {
            handler.close();
        }

        //With the handler closed, verify that the process terminates
        assertThrows(IllegalStateException.class, () -> handler.getInfo(COMMIT_ID));
        future.get(1, TimeUnit.SECONDS); //Should not throw
    }
}