package com.atlassian.bitbucket.internal.integration.jira.web;

import com.atlassian.bitbucket.integration.jira.JiraConstants;
import com.atlassian.bitbucket.integration.jira.JiraIssue;
import com.atlassian.bitbucket.internal.integration.jira.InternalJiraIssueService;
import com.atlassian.bitbucket.internal.integration.jira.SimpleJiraIssue;
import com.atlassian.bitbucket.commit.Commit;
import com.atlassian.bitbucket.property.PropertyMap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.collection.IsMapContaining.hasEntry;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;

@RunWith(MockitoJUnitRunner.class)
public class SimpleJiraIssueContextProviderTest {

    @Mock
    private Commit commit;
    @InjectMocks
    private SimpleJiraIssueContextProvider contextProvider;
    @Mock
    private InternalJiraIssueService jiraService;
    @Mock
    private PropertyMap properties;

    @Before
    public void setup() {
        when(commit.getProperties()).thenReturn(properties);
    }

    @SuppressWarnings("unchecked")
    @Test
    public void testGetContextMapForMultipleIssues() {
        when(properties.get(JiraConstants.IDX_PROP_ISSUE_KEYS))
                .thenReturn(ImmutableSet.of("STASH-3", "ANERD-2", "ANERD-10", "STASH-23"));

        when(jiraService.findIssuesByKey(anySet())).thenReturn(ImmutableList.<JiraIssue>of(
            new SimpleJiraIssue("ANERD-2", "URL"),
            new SimpleJiraIssue("ANERD-10", "URL"),
            new SimpleJiraIssue("STASH-3", "URL"),
            new SimpleJiraIssue("STASH-23", "URL")
        ));

        Map<String, Object> context = contextProvider.getContextMap(Collections.<String, Object>singletonMap("commit", commit));
        assertThat(context, hasEntry(equalTo("issues"), instanceOf(Iterable.class)));

        Iterator<JiraIssue> it = ((Iterable) context.get("issues")).iterator();
        assertEquals("ANERD-2", it.next().getKey());
        assertEquals("ANERD-10", it.next().getKey());
        assertEquals("STASH-3", it.next().getKey());
        assertEquals("STASH-23", it.next().getKey());
        assertFalse("issueKeys should only contain 4 elements", it.hasNext());
    }

    @Test
    public void testGetContextMapForSingleIssue() {
        Set<String> issueKeys = Collections.singleton("STASH-2471");

        when(properties.get(eq(JiraConstants.IDX_PROP_ISSUE_KEYS)))
                .thenReturn(issueKeys);
        when(jiraService.findIssuesByKey(eq(issueKeys)))
                .thenReturn(ImmutableList.<JiraIssue>of(new SimpleJiraIssue("STASH-2471", "http://example.com/jira/browse/STASH-2471")));

        Map<String, Object> context = contextProvider.getContextMap(Collections.<String, Object>singletonMap("commit", commit));
        assertThat(context, hasEntry(equalTo("issues"), instanceOf(Iterable.class)));
        SimpleJiraIssue issue = (SimpleJiraIssue) Iterables.getOnlyElement((Iterable) context.get("issues"));
        assertEquals("STASH-2471", issue.getKey());
        assertEquals("http://example.com/jira/browse/STASH-2471", issue.getUrl());
    }

    @Test
    public void testGetContextMapWithNoIssues() {
        when(properties.get(JiraConstants.IDX_PROP_ISSUE_KEYS)).thenReturn(Collections.<String>emptySet());

        Map<String, Object> context = contextProvider.getContextMap(Collections.<String, Object>singletonMap("commit", commit));
        assertThat(context, hasEntry(equalTo("issues"), instanceOf(Iterable.class)));
        assertTrue("issues should be empty", Iterables.isEmpty((Iterable) context.get("issues")));
    }
}
