package fr.inria.spirals.repairnator;

import fr.inria.spirals.jtravis.entities.Build;
import org.apache.maven.cli.MavenCli;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.RemoteAddCommand;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.transport.URIish;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;

/**
 * Created by urli on 26/12/2016.
 */
public class ProjectInspector {
    public static final String GITHUB_ROOT_REPO = "https://github.com/";

    private Build build;
    private String repoLocalPath;
    private boolean canBeBuilt;
    private boolean canBeCloned;

    public ProjectInspector(Build failingBuild) {
        this.build = failingBuild;
        this.canBeBuilt = false;
        this.canBeCloned = true;
    }

    public boolean canBeBuilt() {
        return this.canBeBuilt;
    }

    public Build getBuild() {
        return this.build;
    }

    public boolean canBeCloned() {
        return this.canBeCloned;
    }

    public void cloneInWorkspace(String workspace) {
        String repository = this.build.getRepository().getSlug();
        this.repoLocalPath = workspace+File.separator+repository;
        String repoRemotePath = GITHUB_ROOT_REPO+repository+".git";

        try {
            Launcher.LOGGER.debug("Cloning repository "+repository+" has in the following directory: "+repoLocalPath);
            Git git = Git.cloneRepository()
                    .setURI(repoRemotePath)
                    .setDirectory(new File(repoLocalPath))
                    .call();

            if (this.build.isPullRequest()) {
                Launcher.LOGGER.debug("Reproduce the PR for "+repository+" by fetching remote branch and merging.");
                String remoteBranchPath = GITHUB_ROOT_REPO+build.getPRRepository().getSlug()+".git";

                RemoteAddCommand remoteBranchCommand = git.remoteAdd();
                remoteBranchCommand.setName("PR");
                remoteBranchCommand.setUri(new URIish(remoteBranchPath));
                remoteBranchCommand.call();

                git.fetch().setRemote("PR").call();

                String commitCheckout = this.build.getHeadCommit().getSha();

                Launcher.LOGGER.debug("Get the commit "+commitCheckout+" for repo "+repository);
                git.checkout().setName(commitCheckout).call();

                Launcher.LOGGER.debug("Do the merge with the PR commit for repo "+repository);
                Ref prCommitRef = git.getRepository().exactRef(this.build.getCommit().getSha());
                git.merge().include(prCommitRef).call();
            } else {
                String commitCheckout = this.build.getCommit().getSha();

                Launcher.LOGGER.debug("Get the commit "+commitCheckout+" for repo "+repository);
                git.checkout().setName(commitCheckout).call();
            }



        } catch (Exception e) {
            Launcher.LOGGER.warn("Repository "+repository+" cannot be cloned.");
            Launcher.LOGGER.debug(e.getMessage());
            this.canBeCloned = false;
        }

        MavenCli cli = new MavenCli();

        System.setProperty("maven.test.skip","true");
        int result = cli.doMain(new String[]{"test"},
                repoLocalPath,
                System.out, System.err);

        if (result == 0) {
            this.canBeBuilt = true;
        } else {
            Launcher.LOGGER.info("Repository "+repository+" cannot be built. It will be ignored for the following steps.");
        }
        System.setProperty("maven.test.skip","false");
    }
}

@@ -201,173 +201,8 @@
 nd;%0A
-import org.eclipse.jgit.api.errors.GitAPIException;%0Aimport org.eclipse.jgit.api.errors.JGitInternalException;%0Aimport org.eclipse.jgit.errors.MissingObjectException;%0A
 impo
@@ -297,72 +297,8 @@
 ile;
-%0Aimport java.io.IOException;%0Aimport java.net.URISyntaxException;
 %0A%0A/*
@@ -2087,32 +2087,107 @@
 tring commit
-Checkout
+HeadSha = this.build.getHeadCommit().getSha();%0A                String commitBaseSha
  = this.buil
@@ -2183,36 +2183,36 @@
 = this.build.get
-Head
+Base
 Commit().getSha(
@@ -2235,151 +2235,746 @@
     
-Launcher.LOGGER.debug(%22Get the commit %22+commitCheckout+%22 for repo %22+repository);%0A                git.checkout().setName(commitCheckout).call();
+Ref commitHeadRef = git.getRepository().exactRef(commitHeadSha);%0A                Ref commitBaseRef = git.getRepository().exactRef(commitBaseSha);%0A%0A                if (commitHeadRef == null) %7B%0A                    Launcher.LOGGER.warn(%22Commit head ref cannot be retrieved in the repository: %22+commitHeadSha);%0A                    Launcher.LOGGER.debug(this.build.getHeadCommit());%0A                    this.canBeCloned = false;%0A                %7D%0A%0A                if (commitBaseRef == null) %7B%0A                    Launcher.LOGGER.warn(%22Commit base ref cannot be retrieved in the repository: %22+commitBaseSha);%0A                    Launcher.LOGGER.debug(this.build.getBaseCommit());%0A                    this.canBeCloned = false;%0A                %7D%0A
 %0A%0A  
@@ -3014,39 +3014,40 @@
 ug(%22
-Do
+Get
  the 
-merge with the PR commit
+commit %22+commitHeadSha+%22
  for
@@ -3087,86 +3087,147 @@
     
-Ref prCommitRef = git.getRepository().exactRef(this.build.getCommit().getSha()
+git.checkout().setName(commitHeadSha).call();%0A%0A                Launcher.LOGGER.debug(%22Do the merge with the PR commit for repo %22+repository
 );%0A 
@@ -3265,16 +3265,18 @@
 ude(
-prC
+c
 ommit
+Base
 Ref)
@@ -3709,18 +3709,16 @@
 g(e.
-getMessage
+toString
 ());

add some validation to check if references can be retrieved to do the merge