package com.atlassian.stash.internal.scm.git.command.foreachref;

import com.atlassian.bitbucket.repository.Branch;
import com.atlassian.bitbucket.scm.git.GitRefPattern;
import com.atlassian.bitbucket.util.Page;
import com.atlassian.bitbucket.util.PageRequest;
import com.atlassian.bitbucket.util.PageUtils;
import com.atlassian.utils.process.Watchdog;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.core.io.ClassPathResource;

import java.util.List;
import java.util.Set;

import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;

public class BranchPagedForEachRefHandlerOutputTest {

    @Test
    public void testExecute() throws Exception {
        PagedForEachRefOutputHandler<Branch> handler = createHandler(null, PageUtils.newRequest(0, 5));
        handler.setWatchdog(mock(Watchdog.class));
        handler.process(new ClassPathResource("git-for-each-ref-branches.out", getClass()).getInputStream());

        Page<Branch> page = handler.getOutput();
        assertNotNull(page);
        assertFalse(page.getIsLastPage());
        assertEquals(5, page.getSize());

        List<Branch> branches = ImmutableList.copyOf(page.getValues());
        assertDefaultBranch("master", "29f078fab2676ca6060b35856912a3e3eae83920", branches.get(0));
        assertBranch("STASH-1842-remove-repo-desc", "e97733eb35803c8295dd31669d0345005bfd3fa3", branches.get(1));
        assertBranch("STASH-1644-source-dist", "39982ea9128abd0d863a522385b9285a8eec092e", branches.get(2));
        assertBranch("STASH-2091-mstudman-no-more-xss-for-extensionless-files",
                "305c7f360d724e44636939e088f6f7527d09fbfd", branches.get(3));
        assertBranch("STASH-1623-applinks-spi", "41d6cd0545dc07505761d450d5563910447602fb", branches.get(4));

        handler = createHandler(null, page.getNextPageRequest());
        handler.setWatchdog(mock(Watchdog.class));
        handler.process(new ClassPathResource("git-for-each-ref-branches.out", getClass()).getInputStream());

        page = handler.getOutput();
        assertNotNull(page);
        assertTrue(page.getIsLastPage());
        assertEquals(5, page.getSize());

        branches = ImmutableList.copyOf(page.getValues());
        assertBranch("STASH-187-embcwd-admin-spi-impl", "cdf62689db0f4c8db2174df13abf28422cf864f2", branches.get(0));
        assertBranch("STASH-2074-bturner-repo-sizes", "75b000a2d034de415c43b14862cfabcf8ead3f6c", branches.get(1));
        assertBranch("STASH-1970-bturner-lock-home", "3c5fa96052ad4c20938ccd7121c9ffd19773e23c", branches.get(2));
        assertBranch("1.0", "a547847107467789bb3e6b61b0dc5440e5ba9717", branches.get(3));
        assertBranch("STASH-1974-autosuggest-project-keys", "f6ed98594fc0bcfbabbece623845c8ff19ca6763",
                branches.get(4));
    }

    @Test
    public void testExecuteWithFilterText() throws Exception {
        PagedForEachRefOutputHandler<Branch> handler = createHandler("stash", PageUtils.newRequest(0, 10));
        handler.setWatchdog(mock(Watchdog.class));
        handler.process(new ClassPathResource("git-for-each-ref-branches.out", getClass()).getInputStream());

        Page<Branch> page = handler.getOutput();
        assertNotNull(page);
        assertTrue(page.getIsLastPage());
        assertEquals(8, page.getSize());

        Set<String> commitIds = Sets.newHashSet("e97733eb35803c8295dd31669d0345005bfd3fa3",
                "39982ea9128abd0d863a522385b9285a8eec092e", "305c7f360d724e44636939e088f6f7527d09fbfd",
                "41d6cd0545dc07505761d450d5563910447602fb", "cdf62689db0f4c8db2174df13abf28422cf864f2",
                "75b000a2d034de415c43b14862cfabcf8ead3f6c", "3c5fa96052ad4c20938ccd7121c9ffd19773e23c",
                "f6ed98594fc0bcfbabbece623845c8ff19ca6763");

        List<Branch> branches = ImmutableList.copyOf(page.getValues());
        for (Branch branch : branches) {
            assertTrue(branch.getId().startsWith("refs/heads/STASH"));
            assertTrue(branch.getDisplayId().startsWith("STASH"));
            assertTrue(commitIds.remove(branch.getLatestCommit()));
            assertFalse(branch.getIsDefault());
        }
        assertTrue(commitIds.isEmpty());
    }

    private static void assertBranch(String displayId, String latestCommit, Branch branch) {
        Assert.assertEquals(GitRefPattern.HEADS.qualify(displayId), branch.getId());
        assertEquals(displayId, branch.getDisplayId());
        assertEquals(latestCommit, branch.getLatestCommit());
    }

    private static void assertDefaultBranch(String displayId, String latestCommit, Branch branch) {
        assertBranch(displayId, latestCommit, branch);
        assertTrue(branch.getIsDefault());
    }

    private static PagedForEachRefOutputHandler<Branch> createHandler(String filterText, PageRequest pageRequest) {
        return new PagedForEachRefOutputHandler<>(new ForEachBranchParser("refs/heads/master"), filterText, pageRequest);
    }
}
