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

import com.atlassian.bitbucket.repository.Tag;
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 org.junit.Assert;
import org.junit.Test;
import org.springframework.core.io.ClassPathResource;

import java.util.List;

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

public class TagPagedForEachRefOutputHandlerTest {

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

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

        List<Tag> tags = ImmutableList.copyOf(page.getValues());
        assertTag("v1.7.8.1", "a22731114e", "2ce0edcd78", tags.get(0));
        assertTag("v1.7.7.5", "b36dcd7239", "66c11f02b0", tags.get(1));
        assertTag("v1.7.6.5", "8634b0870b", "15b7898c5e", tags.get(2));
        assertTag("gitgui-0.16.0", "3da5ebb0ea", "942e6baa92", tags.get(3));
        assertTag("v1.7.8", "8b891d2711", "406da78032", tags.get(4));
    }

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

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

        List<Tag> tags = ImmutableList.copyOf(page.getValues());
        assertTag("retagged_signed_tag", "9b4e781dea07", "12ebe2a58367", tags.get(0));
        assertTag("signed_tag", "12ebe2a58367", "0a943a29376f", tags.get(1));
        assertTag("a", "0a943a29376f", tags.get(2)); //lightweight
        assertTag("b", "0a943a29376f", tags.get(3)); //lightweight
        assertTag("backdated_annotated_tag", "80aa5be5ecf3", "57150c54c38d", tags.get(4));
        assertTag("c", "8fb8538799b2", tags.get(5)); //lightweight
    }

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

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

        List<Tag> tags = ImmutableList.copyOf(page.getValues());
        assertTag("v1.7.8.1", "a22731114e", "2ce0edcd78", tags.get(0));
        assertTag("v1.7.8", "8b891d2711", "406da78032", tags.get(1));
        assertTag("v1.7.8-rc4", "f96a6ecfb8", "fc14b89a7e", tags.get(2));
        assertTag("v1.7.8-rc3", "a679394397", "4d2440fe0d", tags.get(3));
        assertTag("v1.7.8-rc2", "9765e24e02", "bc1bbe0c19", tags.get(4));
    }

    private static void assertTag(String displayId, String latestCommit, Tag tag) {
        assertTag(displayId, null, latestCommit, tag);
    }

    private static void assertTag(String displayId, String hash, String latestCommit, Tag tag) {
        Assert.assertEquals(GitRefPattern.TAGS.qualify(displayId), tag.getId());
        assertEquals(displayId, tag.getDisplayId());
        if (hash == null) {
            assertNull(tag.getHash());
        } else {
            assertNotNull(tag.getHash());
            assertTrue(tag.getHash().startsWith(hash));
        }
        assertTrue(tag.getLatestCommit().startsWith(latestCommit));
    }

    private static PagedForEachRefOutputHandler<Tag> createHandler(String filterText, PageRequest pageRequest) {
        return new PagedForEachRefOutputHandler<>(ForEachTagParser.INSTANCE, filterText, pageRequest);
    }
}
