package hu.sebcsaba.gitrelocate;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

public class GitCmdLineRunner implements GitRunner {
	
	private final CmdLineTool cmdLine;
	
	public GitCmdLineRunner(CmdLineTool cmdLine) {
		this.cmdLine = cmdLine;
	}
	
	public CommitID getCommitId(String anyGitCommitRef) {
		return new CommitID(gitString("rev-parse", anyGitCommitRef).trim());
	}
	
	public List<CommitID> getCommitParentIds(CommitID commitId) {
		return getCommitIDList(gitStringList("log", "--pretty=%P", "-n", "1", commitId.toString()));
	}
	
	public Collection<String> getTagNames() {
		return gitStringList("tag");
	}
	
	public Collection<String> getBranchNames() {
		List<String> result = gitStringList("branch");
		result.remove("*");
		return result;
	}
	
	public String getActualHeadName() {
		String head = gitString("rev-parse", "--abbrev-ref", "HEAD");
		if ("HEAD".equals(head)) {
			head = gitString("rev-parse", "HEAD");
		}
		return head.trim();
	}

	public void createBranch(String branchName) {
		gitExec("branch", branchName);
	}

	public void createBranch(String branchName, CommitID commitId) {
		gitExec("branch", branchName, commitId.toString());
	}

	public void removeBranch(String branchName) {
		gitExec("branch", "-D", branchName);
	}

	public void moveBranch(String branchName, CommitID commitId) {
		String head = getActualHeadName();
		checkOut(branchName);
		gitExec("reset", "--hard", commitId.toString());
		checkOut(head);
	}

	public void checkOut(String branchName) {
		gitExec("checkout", "-f", branchName);
	}

	public void createTag(String tagName) {
		gitExec("tag", tagName);
	}

	public void createTag(String tagName, CommitID commitId) {
		gitExec("tag", tagName, commitId.toString());
	}

	public void removeTag(String tagName) {
		gitExec("tag", "-d", tagName);
	}

	public CommitID cherryPick(CommitID commitId) {
		gitExec("cherry-pick", commitId.toString());
		return getCommitId("HEAD");
	}

	public CommitID cherryPickMergeCommit(CommitID commitId, List<CommitID> newParentsIds) {
		try {
			gitExec("cherry-pick", "--no-ff", "--no-commit", "--mainline", "1", commitId.toString());
			String treeId = gitString("write-tree").trim();
			String message = getCommitMessage(commitId);

			List<String> commitParams = new ArrayList<String>();
			commitParams.addAll(Arrays.asList("git", "commit-tree", treeId));
			for (CommitID newParentId : newParentsIds) {
				commitParams.add("-p");
				commitParams.add(newParentId.toString());
			}
			String commit = cmdLine.withInput(message).getString(commitParams.toArray(new String[commitParams.size()])).trim();
			return new CommitID(commit);
		} catch (IOException ex) {
			throw new RuntimeException(ex);
		}
	}

	private String getCommitMessage(CommitID commitId) {
		StringBuilder result = new StringBuilder();
		String[] list = gitString("show", "--format=full", commitId.toString()).split("\\r?\\n");
		for (int i=5; i<list.length; ++i) {
			result.append(list[i]).append("\n");
		}
		return result.toString();
	}

	private void gitExec(String... params) {
		try {
			cmdLine.run(unshift("git", params));
		}
		catch (IOException ex) {
			throw new RuntimeException(ex);
		}
	}
	
	private String gitString(String... params) {
		try {
			return cmdLine.getString(unshift("git", params));
		}
		catch (IOException ex) {
			throw new RuntimeException(ex);
		}
	}
	
	private List<String> gitStringList(String... params) {
		try {
			return cmdLine.getStringList(unshift("git", params));
		}
		catch (IOException ex) {
			throw new RuntimeException(ex);
		}
	}
	
	private List<CommitID> getCommitIDList(List<String> ids) {
		List<CommitID> result = new ArrayList<CommitID>(ids.size());
		for (String id : ids) {
			result.add(new CommitID(id));
		}
		return result;
	}
	
	private String[] unshift(String first, String[] rest) {
		String[] result = new String[rest.length+1];
		result[0] = first;
		System.arraycopy(rest, 0, result, 1, rest.length);
		return result;
	}

}

@@ -449,23 +449,16 @@
 mmitRef)
-.trim()
 );%0A%09%7D%0A%09%0A
@@ -2249,23 +2249,16 @@
 e-tree%22)
-.trim()
 ;%0A%09%09%09Str
@@ -2902,16 +2902,21 @@
 itString
+Lines
 (%22show%22,
@@ -2957,25 +2957,8 @@
 g())
-.split(%22%5C%5Cr?%5C%5Cn%22)
 ;%0A%09%09
@@ -3331,32 +3331,245 @@
 (%22git%22, params))
+.trim();%0A%09%09%7D%0A%09%09catch (IOException ex) %7B%0A%09%09%09throw new RuntimeException(ex);%0A%09%09%7D%0A%09%7D%0A%09%0A%09private String%5B%5D gitStringLines(String... params) %7B%0A%09%09try %7B%0A%09%09%09return cmdLine.getString(unshift(%22git%22, params)).split(%22%5C%5Cr?%5C%5Cn%22)
 ;%0A%09%09%7D%0A%09%09catch (I

use trim() on gitString()