package com.atlassian.stash.internal.task.property;

import com.atlassian.stash.internal.comment.InternalComment;
import com.atlassian.stash.internal.pull.InternalPullRequest;
import com.atlassian.stash.internal.pull.InternalPullRequestDiffCommentAnchor;
import com.atlassian.stash.internal.pull.PullRequestCommentAnchorDao;
import com.atlassian.stash.internal.task.InternalTask;
import com.atlassian.stash.internal.task.InternalTaskContextVisitor;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterators;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.runners.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;

import java.util.Set;

import static com.atlassian.stash.internal.task.property.DiffAnchorTaskPropertyProvider.ATTRIBUTE_KEY;
import static org.hamcrest.Matchers.contains;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.argThat;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.same;
import static org.mockito.Mockito.*;

@RunWith(MockitoJUnitRunner.class)
public class DiffAnchorTaskPropertyProviderTest {

    @Mock
    private PullRequestCommentAnchorDao anchorDao;

    @InjectMocks
    private DiffAnchorTaskPropertyProvider provider;

    @SuppressWarnings("unchecked")
    @Test
    public void testProvideAttributes() throws Exception {
        InternalPullRequest pullRequest = new InternalPullRequest.Builder().globalId(1L).build();
        InternalComment rootComment = new InternalComment.Builder().id(42L).build();
        InternalComment taskComment = new InternalComment.Builder().id(43L).root(rootComment).build();
        InternalTask task = new InternalTask.Builder().anchor(taskComment).build();
        TaskPropertyContext context = mockContext(pullRequest, task);

        InternalPullRequestDiffCommentAnchor commentAnchor = new InternalPullRequestDiffCommentAnchor.Builder(pullRequest).comment(rootComment).path("path/to/file.txt").build();
        when(anchorDao.findByCommentIds((Set<Long>) argThat(contains(rootComment.getId())))).thenReturn(ImmutableList.of(commentAnchor));

        provider.provideProperties(context);

        verify(context).setProperty(same(task), eq(ATTRIBUTE_KEY), eq("path/to/file.txt"));
    }

    private static TaskPropertyContext mockContext(final InternalPullRequest pullRequest, InternalTask... tasks) {
        TaskPropertyContext context = mock(TaskPropertyContext.class);
        when(context.accept(any(InternalTaskContextVisitor.class))).thenAnswer(new Answer<Object>() {
            @Override
            public Object answer(InvocationOnMock invocation) throws Throwable {
                return ((InternalTaskContextVisitor) invocation.getArguments()[0]).visit(pullRequest);
            }
        });
        when(context.iterator()).thenReturn(Iterators.forArray(tasks));
        return context;
    }
}