package tdl.record.sourcecode.content;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import tdl.record.sourcecode.test.FileTestHelper;

public class CopyFromDirectorySourceCodeProviderTest {

    @Rule
    public TemporaryFolder folder = new TemporaryFolder();
    private Git git;
    private CopyFromDirectorySourceCodeProvider provider;
    private Path sourceFolderPath;
    private Path destination;
    private SourceFolder sourceFolder;


    @Before
    public void setUp() throws Exception {
        File sourceFolderFile = folder.newFolder();
        this.sourceFolderPath = sourceFolderFile.toPath();
        destination = folder.newFolder().toPath();
        sourceFolder = new SourceFolder(sourceFolderPath);

        git = Git.init().setDirectory(sourceFolderFile).call();

        provider = new CopyFromDirectorySourceCodeProvider(this.sourceFolderPath);
    }


    @Test
    public void shouldDetectGitRepo() throws Exception {
        assertTrue(provider.isGit());
    }

    @Test
    public void shouldWorkWithSubFolders() throws IOException, GitAPIException {
        sourceFolder.createFiles("subdir1/file1.txt");

        git.add().addFilepattern(".").call();
        git.commit().setMessage("commit1").call();

        sourceFolder.createFiles("subdir1/untracked.txt");

        provider.retrieveAndSaveTo(destination);

        assertExistsInDestination(
                "subdir1/file1.txt",
                "subdir1/untracked.txt");
    }


    @Test
    public void shouldHonourGitignoreContent() throws IOException, GitAPIException {
        sourceFolder.createFiles(
                "ok.txt",
                "file1.bak");
        sourceFolder.appendTo(".gitignore", "*.bak");

        git.add().addFilepattern(".").call();
        git.commit().setMessage("commit1").call();

        sourceFolder.createFiles("file2.bak");

        provider.retrieveAndSaveTo(destination);

        assertExistsInDestination(
                "ok.txt",
                ".gitignore");
        assertNotExistsInDestination(
                "file1.bak",
                "file2.bak");
    }

    @Test
    public void shouldWorkWithDeletedFiles() throws IOException, GitAPIException {
        sourceFolder.createFiles(
                "file.to.keep.txt",
                "file.to.remove.txt");
        git.add().addFilepattern(".").call();
        git.commit().setMessage("commit1").call();

        sourceFolder.deleteFiles("file.to.remove.txt");

        provider.retrieveAndSaveTo(destination);

        assertExistsInDestination("file.to.keep.txt");
        assertNotExistsInDestination("file.to.remove.txt");
    }



    //~~~~~~~~~~~ Helpers
    static class SourceFolder {

        private Path sourceFolderPath;
        SourceFolder(Path sourceFolderPath) {
            this.sourceFolderPath = sourceFolderPath;
        }

        private void createFiles(String ... filesToCreate) throws IOException {
            for (String file : filesToCreate) {
                FileTestHelper.appendStringToFile(sourceFolderPath, file, "TEST");
            }
        }

        private void appendTo(String file, String content) throws IOException {
            FileTestHelper.appendStringToFile(sourceFolderPath, file, content);
        }

        private void deleteFiles(String ... filesToRemove) {
            for (String fileToRemove : filesToRemove) {
                FileTestHelper.deleteFile(sourceFolderPath, fileToRemove);
            }
        }
    }


    private void assertNotExistsInDestination(String ... filesToCheck) {
        for (String fileToCheck : filesToCheck) {
            assertFalse("File "+fileToCheck+" found in destination",
                    exists(destination, fileToCheck));
        }
        assertFalse(exists(destination, ".git"));
    }

    private void assertExistsInDestination(String ... filesToCheck) {
        for (String fileToCheck : filesToCheck) {
            assertTrue("File "+fileToCheck+" not present in destination",
                    exists(destination, fileToCheck));
        }
    }

    private static boolean exists(Path parent, String filename) {
        return Files.exists(parent.resolve(filename));
    }

}

@@ -1207,33 +1207,32 @@
 erPath);%0A    %7D%0A%0A
-%0A
     @Test%0A    pu
@@ -1251,17 +1251,21 @@
 ould
-DetectGit
+WorkWithEmpty
 Repo
@@ -1266,32 +1266,51 @@
 tyRepo() throws 
+IOException, GitAPI
 Exception %7B%0A    
@@ -1342,16 +1342,113 @@
 sGit());
+%0A%0A        provider.retrieveAndSaveTo(destination);%0A%0A        assertNotExistsInDestination(%22.git%22);
 %0A    %7D%0A%0A
@@ -2743,32 +2743,88 @@
 %22file.to.remove.
+tracked.txt%22,%0A                %22file.to.remove.untracked.
 txt%22);%0A        g
@@ -2962,21 +2962,143 @@
 remove.t
-xt%22);
+racked.txt%22);%0A        git.add().addFilepattern(%22.%22).call();%0A%0A        sourceFolder.deleteFiles(%22file.to.remove.untracked.txt%22);%0A
 %0A%0A      
@@ -3237,37 +3237,584 @@
 ion(
-%22file.to.remove.txt%22);%0A    %7D%0A
+%0A                %22file.to.remove.tracked.txt%22,%0A                %22file.to.remove.untracked.txt%22%0A        );%0A    %7D%0A%0A%0A    @Test%0A    public void shouldWorkWithUncommitedFiles() throws IOException, GitAPIException %7B%0A        git.commit().setMessage(%22initialCommit%22).call();%0A%0A        sourceFolder.createFiles(%22uncommited.txt%22);%0A        git.add().addFilepattern(%22.%22).call();%0A%0A        sourceFolder.createFiles(%22untracked.txt%22);%0A%0A        provider.retrieveAndSaveTo(destination);%0A%0A        assertExistsInDestination(%0A                %22uncommited.txt%22,%0A                %22untracked.txt%22);%0A    %7D
 %0A%0A%0A 
@@ -4249,32 +4249,80 @@
    %7D%0A        %7D%0A%0A
+        @SuppressWarnings(%22SameParameterValue%22)%0A
         private 

Add test to expose a bug where a new file that is tracked is not being picked up for copying