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

import com.atlassian.bitbucket.content.Change;
import com.atlassian.bitbucket.content.ChangeType;
import com.atlassian.bitbucket.content.ContentTreeNode;
import com.atlassian.bitbucket.util.Page;
import com.atlassian.bitbucket.util.PageRequestImpl;
import com.atlassian.utils.process.Watchdog;
import com.google.common.collect.ImmutableList;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.core.io.ClassPathResource;

import java.io.ByteArrayInputStream;
import java.util.List;

@SuppressWarnings("ConstantConditions")
public class ChangeDiffTreeOutputHandlerTest {

    @Test
    public void testExecute() throws Exception {
        ChangeDiffTreeOutputHandler handler = new ChangeDiffTreeOutputHandler(new PageRequestImpl(0, 10));
        handler.setWatchdog(Mockito.mock(Watchdog.class));
        handler.process(new ClassPathResource("git-diff-tree.out", getClass()).getInputStream());
        
        Page<Change> page = handler.getOutput();
        Assert.assertNotNull(page);
        Assert.assertFalse(page.getIsLastPage());
        Assert.assertEquals(10, page.getSize());
        
        List<Change> changes = ImmutableList.copyOf(page.getValues());
        assertChange("2b44a9bc563279cbb4e63cc30de7e1d3bec27293",
                "056bedb48742f473ee6ed936d1f45af9f5a92aab",
                "core/src/test/java/com/atlassian/stash/nav/NavBuilderImplTest.java",
                changes.get(0));
        assertChange("c0cc58a36c2dcaa6864a1bc5a882c3bdb98d137b",
                "d4568522521453e84cc06e52ad23fe4878107dab",
                "plugins/rest/src/main/java/com/atlassian/stash/rest/data/RestRepository.java",
                changes.get(1));
        assertChange("ad167cd84e9757d40525021fabae13c2ce6fc4e2",
                "b33662825fd8d89892767f0091e8d40ea64addef",
                "plugins/rest/src/main/java/com/atlassian/stash/rest/project/ProjectResource.java",
                changes.get(2));
        assertChange("65a4e69c30e8a71dfeb6bb6fbf6a11a5be066c2f",
                "d3d10015b043d92edcf0f434dc4cdf886c828b5d",
                "plugins/rest/src/main/java/com/atlassian/stash/rest/repository/RepositoryResource.java",
                changes.get(3));
        assertChange("69cebe18f994a7c77b5a383d1ca06f2e68788a20",
                "969978e6310bcaaa10a33b3883242fd02587fa61",
                "plugins/rest/src/main/java/com/atlassian/stash/rest/user/PermissionAdminManager.java",
                changes.get(4));
        assertChange("cc0a2ddd5908ebeda1c43006d8b15e7e089665eb",
                "3a17924a6c281db5f61bc2f585d2b772749a1c5c",
                "plugins/rest/src/main/java/com/atlassian/stash/rest/util/RestResource.java",
                changes.get(5));
        assertChange("c20d654e62f5cc07c443ced32c651fcbd1627be3",
                "47d9b70b8bc5b709263958b2715e02679572d8c4",
                "pom.xml",
                changes.get(6));
        assertChange("bbce5bc764f45e2feaeacffd9fc47613799f166f",
                "4438d809c22ebaa90fcfd236dcc68e734c3eeb40",
                "webapp/standalone/src/main/webapp/static/page/filebrowser/filebrowser.soy",
                changes.get(7));
        assertChange("43ec0b8c274f3fbed66d4ed12433cc652cfc592e",
                "41be9952630ac42d4d7208adce24e1afe6db7217",
                "webapp/standalone/src/main/webapp/static/widget/branch_selector/branch_selector.js",
                changes.get(8));
        assertChange("0623693e95c6a450f05cfa8e9ce51f21bfef37d7",
                "9f8f29be30d18a30dacd12400e28812cfbc7228e",
                "webapp/standalone/src/main/webapp/static/widget/branch_selector/branch_selector_dialog.js",
                changes.get(9));

        handler = new ChangeDiffTreeOutputHandler(page.getNextPageRequest());
        handler.setWatchdog(Mockito.mock(Watchdog.class));
        handler.process(new ClassPathResource("git-diff-tree.out", getClass()).getInputStream());

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

        changes = ImmutableList.copyOf(page.getValues());
        assertChange("30e8e72ec50d95e0655f08c18bce20a3992823a7",
                "bc81174d308446da8f5e3eba94ec70f77d7e7ba4",
                "webapp/standalone/src/test/java/com/atlassian/stash/web/soy/functions/nav/NavSoyFunctionsTest.java",
                changes.get(0));
    }

    @Test
    public void testSubmodule() throws Exception {
        ChangeDiffTreeOutputHandler handler = new ChangeDiffTreeOutputHandler(new PageRequestImpl(0, 10));
        handler.setWatchdog(Mockito.mock(Watchdog.class));
        handler.process(new ByteArrayInputStream(":000000 160000 056bedb48742f473ee6ed936d1f45af9f5a92aab 2b44a9bc563279cbb4e63cc30de7e1d3bec27293 M\tsubmodule\n".getBytes()));

        List<Change> changes = ImmutableList.copyOf(handler.getOutput().getValues());
        Assert.assertEquals(ContentTreeNode.Type.SUBMODULE, changes.get(0).getNodeType());
    }

    @Test
    public void testSubmoduleConflict() throws Exception {
        ChangeDiffTreeOutputHandler handler = new ChangeDiffTreeOutputHandler(new PageRequestImpl(0, 10));
        handler.setWatchdog(Mockito.mock(Watchdog.class));
        handler.process(new ByteArrayInputStream(":160000 100644 056bedb48742f473ee6ed936d1f45af9f5a92aab 2b44a9bc563279cbb4e63cc30de7e1d3bec27293 T\tsubmodule\n".getBytes()));

        List<Change> changes = ImmutableList.copyOf(handler.getOutput().getValues());
        Assert.assertEquals(ContentTreeNode.Type.SUBMODULE, changes.get(0).getNodeType());
    }

    private static void assertChange(String contentId, String fromContentId, String path, Change change) {
        assertChange(contentId, fromContentId, path, null, ChangeType.MODIFY, -1, change);
    }

    private static void assertChange(String contentId, String fromContentId, String path, String srcPath, ChangeType type, int score, Change change) {
        Assert.assertEquals(contentId, change.getContentId());
        Assert.assertEquals(fromContentId, change.getFromContentId());
        Assert.assertNotNull(change.getPath());
        Assert.assertEquals(path, change.getPath().toString());
        Assert.assertEquals(score, change.getPercentUnchanged());
        Assert.assertSame(type, change.getType());
        Assert.assertEquals(ContentTreeNode.Type.FILE, change.getNodeType());
        if (srcPath == null) {
            Assert.assertNull(change.getSrcPath());
        } else {
            Assert.assertNotNull(change.getSrcPath());
            Assert.assertEquals(srcPath, change.getSrcPath().toString());
        }
    }
}
