// Copyright (C) 2013 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.gerrit.acceptance.git;

import com.google.common.collect.Iterables;
import com.google.gerrit.acceptance.SshSession;
import com.google.gerrit.acceptance.TempFileUtil;
import com.google.gerrit.acceptance.TestAccount;

import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;

import org.eclipse.jgit.api.AddCommand;
import org.eclipse.jgit.api.CloneCommand;
import org.eclipse.jgit.api.CommitCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.PushCommand;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.JschConfigSessionFactory;
import org.eclipse.jgit.transport.OpenSshConfig.Host;
import org.eclipse.jgit.transport.PushResult;
import org.eclipse.jgit.transport.RefSpec;
import org.eclipse.jgit.transport.SshSessionFactory;
import org.eclipse.jgit.util.ChangeIdUtil;
import org.eclipse.jgit.util.FS;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;

public class GitUtil {

  public static void initSsh(final TestAccount a) {
    final Properties config = new Properties();
    config.put("StrictHostKeyChecking", "no");
    JSch.setConfig(config);

    // register a JschConfigSessionFactory that adds the private key as identity
    // to the JSch instance of JGit so that SSH communication via JGit can
    // succeed
    SshSessionFactory.setInstance(new JschConfigSessionFactory() {
      @Override
      protected void configure(Host hc, Session session) {
        try {
          final JSch jsch = getJSch(hc, FS.DETECTED);
          jsch.addIdentity("KeyPair", a.privateKey(),
              a.sshKey.getPublicKeyBlob(), null);
        } catch (JSchException e) {
          throw new RuntimeException(e);
        }
      }
    });
  }

  public static void createProject(SshSession s, String name)
      throws JSchException, IOException {
    s.exec("gerrit create-project --empty-commit --name \"" + name + "\"");
  }

  public static Git cloneProject(String url) throws GitAPIException {
    final File gitDir = TempFileUtil.createTempDirectory();
    final CloneCommand cloneCmd = Git.cloneRepository();
    cloneCmd.setURI(url);
    cloneCmd.setDirectory(gitDir);
    return cloneCmd.call();
  }

  public static void add(Git git, String path, String content)
      throws GitAPIException, IOException {
    File f = new File(git.getRepository().getDirectory().getParentFile(), path);
    File p = f.getParentFile();
    if (!p.exists() && !p.mkdirs()) {
      throw new IOException("failed to create dir: " + p.getAbsolutePath());
    }
    FileWriter w = new FileWriter(f);
    BufferedWriter out = new BufferedWriter(w);
    try {
      out.write(content);
    } finally {
      out.close();
    }

    final AddCommand addCmd = git.add();
    addCmd.addFilepattern(path);
    addCmd.call();
  }

  public static String createCommit(Git git, PersonIdent i, String msg)
      throws GitAPIException, IOException {
    return createCommit(git, i, msg, true);
  }

  public static String createCommit(Git git, PersonIdent i, String msg,
      boolean insertChangeId) throws GitAPIException, IOException {
    ObjectId changeId = null;
    if (insertChangeId) {
      changeId = computeChangeId(git, i, msg);
      msg = ChangeIdUtil.insertId(msg, changeId);
    }

    final CommitCommand commitCmd = git.commit();
    commitCmd.setAuthor(i);
    commitCmd.setCommitter(i);
    commitCmd.setMessage(msg);
    commitCmd.call();

    return changeId != null ? "I" + changeId.getName() : null;
  }

  private static ObjectId computeChangeId(Git git, PersonIdent i, String msg)
      throws IOException {
    RevWalk rw = new RevWalk(git.getRepository());
    try {
      RevCommit parent =
          rw.lookupCommit(git.getRepository().getRef(Constants.HEAD).getObjectId());
      return ChangeIdUtil.computeChangeId(parent.getTree(), parent.getId(), i, i, msg);
    } finally {
      rw.release();
    }
  }

  public static PushResult pushHead(Git git, String ref) throws GitAPIException {
    PushCommand pushCmd = git.push();
    pushCmd.setRefSpecs(new RefSpec("HEAD:" + ref));
    Iterable<PushResult> r = pushCmd.call();
    return Iterables.getOnlyElement(r);
  }
}
