package com.atlassian.bitbucket.internal.branch.list.aheadbehind;

import com.atlassian.bitbucket.commit.MinimalCommit;
import com.atlassian.bitbucket.commit.graph.CommitGraphNode;
import com.atlassian.bitbucket.commit.graph.TraversalStatus;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import org.junit.Test;

import java.util.List;

import static com.atlassian.bitbucket.internal.branch.MetadataProviderTestUtils.mockCommit;
import static com.atlassian.bitbucket.internal.branch.MetadataProviderTestUtils.mockRef;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class AheadBehindTraversalCallbackTest {

    private static final List<List<String>> DATA = ImmutableList.<List<String>>of(
            ImmutableList.of("2a6b", "54db"),
            ImmutableList.of("cc87", "54dd", "54db"),
            ImmutableList.of("54db", "62ae"),
            ImmutableList.of("54dd", "219c", "62ae"),
            ImmutableList.of("62ae", "ef50"),
            ImmutableList.of("219c", "e269"),
            ImmutableList.of("e269", "ef50"),
            ImmutableList.of("ef50")
    );

    @Test
    public void testOnNode() throws Exception {
        AheadBehindTraversalCallback callback = new AheadBehindTraversalCallback(mockRef("branchA", "2a6b"), mockRef("branchB", "cc87"));

        for (CommitGraphNode node : getNodes()) {
            TraversalStatus status = callback.onNode(node);
            assertEquals(node.getCommit().getId(),
                    node.getCommit().getId().equals("e269") ? TraversalStatus.FINISH : TraversalStatus.CONTINUE,
                    status);
            if (status == TraversalStatus.FINISH) {
                break;
            }
        }

        AheadBehindCount count = callback.getCount();
        assertNotNull(count);
        assertEquals(4, count.getAhead());
        assertEquals(1, count.getBehind());
    }

    private List<CommitGraphNode> getNodes() {
        List<CommitGraphNode> nodes = Lists.newArrayList();
        for (List<String> nodeAsStrings : DATA) {
            CommitGraphNode node = mock(CommitGraphNode.class);
            MinimalCommit commit = mockCommit(nodeAsStrings.get(0));
            List<MinimalCommit> parents = Lists.newArrayList();
            for (String parentHash : nodeAsStrings.subList(1, nodeAsStrings.size())) {
                parents.add(mockCommit(parentHash));
            }
            when(node.getCommit()).thenReturn(commit);
            when(node.getParents()).thenReturn(parents);
            nodes.add(node);
        }
        return nodes;
    }

}
