// 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.googlesource.gerrit.plugins.github.git;

import static com.google.gerrit.reviewdb.client.RefNames.REFS_HEADS;

import com.google.common.collect.Lists;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change.Id;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.Project.NameKey;
import com.google.gerrit.server.account.AccountImporter;
import com.google.gerrit.server.account.externalids.ExternalId;
import com.google.gerrit.server.account.externalids.ExternalIds;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectState;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.googlesource.gerrit.plugins.github.git.GitJobStatus.Code;
import com.googlesource.gerrit.plugins.github.oauth.GitHubLogin;
import com.googlesource.gerrit.plugins.github.oauth.ScopedProvider;
import java.io.IOException;
import java.util.List;
import java.util.Optional;
import org.eclipse.jgit.api.FetchCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.InvalidRemoteException;
import org.eclipse.jgit.api.errors.TransportException;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ProgressMonitor;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevSort;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.RefSpec;
import org.kohsuke.github.GHPullRequest;
import org.kohsuke.github.GHPullRequestCommitDetail;
import org.kohsuke.github.GHRepository;
import org.kohsuke.github.GHUser;
import org.kohsuke.github.GitUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class PullRequestImportJob implements GitJob, ProgressMonitor {

  public interface Factory {
    PullRequestImportJob create(
        @Assisted("index") int jobIndex,
        @Assisted("organisation") String organisation,
        @Assisted("name") String repository,
        @Assisted int pullRequestId,
        @Assisted PullRequestImportType importType);
  }

  private static final Logger LOG = LoggerFactory.getLogger(PullRequestImportJob.class);

  private static final String TOPIC_FORMAT = "GitHub #%d";

  private final GitHubRepository ghRepository;
  private final GitHubLogin ghLogin;
  private final String organisation;
  private final String repoName;
  private final int prId;
  private final GitRepositoryManager repoMgr;
  private final int jobIndex;
  private final ExternalIds externalIds;
  private PullRequestCreateChange createChange;
  private Project project;
  private GitJobStatus status;
  private boolean cancelRequested;
  private AccountImporter accountImporter;

  @Inject
  public PullRequestImportJob(
      GitRepositoryManager repoMgr,
      PullRequestCreateChange createChange,
      ProjectCache projectCache,
      AccountImporter accountImporter,
      GitHubRepository.Factory gitHubRepoFactory,
      ScopedProvider<GitHubLogin> ghLoginProvider,
      ExternalIds externalIds,
      @Assisted("index") int jobIndex,
      @Assisted("organisation") String organisation,
      @Assisted("name") String repoName,
      @Assisted int pullRequestId) {
    this.jobIndex = jobIndex;
    this.repoMgr = repoMgr;
    this.ghLogin = ghLoginProvider.get();
    this.organisation = organisation;
    this.repoName = repoName;
    this.prId = pullRequestId;
    this.createChange = createChange;
    this.project = fetchGerritProject(projectCache, organisation, repoName);
    this.ghRepository = gitHubRepoFactory.create(organisation, repoName);
    this.status = new GitJobStatus(jobIndex);
    this.accountImporter = accountImporter;
    this.externalIds = externalIds;
  }

  private Project fetchGerritProject(
      ProjectCache projectCache, String fetchOrganisation, String fetchRepoName) {
    NameKey projectNameKey = Project.NameKey.parse(fetchOrganisation + "/" + fetchRepoName);
    ProjectState projectState = projectCache.get(projectNameKey);
    return projectState.getProject();
  }

  @Override
  public void run() {
    try {
      status.update(GitJobStatus.Code.SYNC);
      exitWhenCancelled();
      GHPullRequest pr = fetchGitHubPullRequestInfo();

      exitWhenCancelled();
      try (Repository gitRepo =
          repoMgr.openRepository(new Project.NameKey(organisation + "/" + repoName))) {
        exitWhenCancelled();
        fetchGitHubPullRequest(gitRepo, pr);

        exitWhenCancelled();
        List<Id> changeIds = addPullRequestToChange(pr, gitRepo);
        status.update(
            GitJobStatus.Code.COMPLETE, "Imported", "PullRequest imported as Changes " + changeIds);
      }
    } catch (JobCancelledException e) {
      status.update(GitJobStatus.Code.CANCELLED);
    } catch (Throwable e) {
      LOG.error(
          "Pull request "
              + prId
              + " into repository "
              + organisation
              + "/"
              + repoName
              + " was failed",
          e);
      status.update(GitJobStatus.Code.FAILED, "Failed", e.getLocalizedMessage());
    }
  }

  private List<Id> addPullRequestToChange(GHPullRequest pr, Repository gitRepo) throws Exception {
    String destinationBranch = REFS_HEADS + pr.getBase().getRef();
    List<Id> prChanges = Lists.newArrayList();
    ObjectId baseObjectId = ObjectId.fromString(pr.getBase().getSha());
    ObjectId prHeadObjectId = ObjectId.fromString(pr.getHead().getSha());

    try (RevWalk walk = new RevWalk(gitRepo)) {
      walk.markUninteresting(walk.lookupCommit(baseObjectId));
      walk.markStart(walk.lookupCommit(prHeadObjectId));
      walk.sort(RevSort.REVERSE);

      int patchNr = 1;
      for (GHPullRequestCommitDetail ghCommitDetail : pr.listCommits()) {
        status.update(
            Code.SYNC,
            "Patch #" + patchNr,
            "Patch#" + patchNr + ": Inserting PullRequest into Gerrit");
        RevCommit revCommit = walk.parseCommit(ObjectId.fromString(ghCommitDetail.getSha()));

        GHUser prUser = pr.getUser();
        GitUser commitAuthor = ghCommitDetail.getCommit().getAuthor();
        GitHubUser gitHubUser = GitHubUser.from(prUser, commitAuthor);

        Account.Id pullRequestOwner = getOrRegisterAccount(gitHubUser);
        Id changeId =
            createChange.addCommitToChange(
                project,
                gitRepo,
                destinationBranch,
                pullRequestOwner,
                revCommit,
                getChangeMessage(pr),
                String.format(TOPIC_FORMAT, new Integer(pr.getNumber())));
        if (changeId != null) {
          prChanges.add(changeId);
        }
      }

      return prChanges;
    }
  }

  private com.google.gerrit.reviewdb.client.Account.Id getOrRegisterAccount(GitHubUser author)
      throws BadRequestException, ResourceConflictException, UnprocessableEntityException,
          IOException, ConfigInvalidException {
    return getOrRegisterAccount(author.getLogin(), author.getName(), author.getEmail());
  }

  private com.google.gerrit.reviewdb.client.Account.Id getOrRegisterAccount(
      String login, String name, String email)
      throws BadRequestException, ResourceConflictException, UnprocessableEntityException,
          IOException, ConfigInvalidException {
    Optional<ExternalId> gerritId = externalIdByScheme(ExternalId.SCHEME_GERRIT, login);
    if (gerritId.isPresent()) {
      return gerritId.get().accountId();
    }
    return accountImporter.importAccount(login, name, email);
  }

  private Optional<ExternalId> externalIdByScheme(String scheme, String id) {
    try {
      return externalIds.get(ExternalId.Key.create(scheme, id));
    } catch (IOException | ConfigInvalidException e) {
      LOG.error("Unable to get external id for " + scheme + ":" + id, e);
      return Optional.empty();
    }
  }

  private String getChangeMessage(GHPullRequest pr) {
    return "GitHub Pull Request: "
        + pr.getHtmlUrl()
        + "\n\n"
        + pr.getTitle()
        + "\n\n"
        + pr.getBody();
  }

  private void exitWhenCancelled() throws JobCancelledException {
    if (cancelRequested) {
      throw new JobCancelledException();
    }
  }

  private void fetchGitHubPullRequest(Repository gitRepo, GHPullRequest pr)
      throws GitAPIException, InvalidRemoteException, TransportException {
    status.update(Code.SYNC, "Fetching", "Fetching PullRequests from GitHub");

    try (Git git = Git.wrap(gitRepo)) {
      FetchCommand fetch = git.fetch();
      fetch.setRemote(ghRepository.getCloneUrl());
      fetch.setRefSpecs(
          new RefSpec(
              "+refs/pull/" + pr.getNumber() + "/head:refs/remotes/origin/pr/" + pr.getNumber()));
      fetch.setProgressMonitor(this);
      fetch.setCredentialsProvider(ghRepository.getCredentialsProvider());
      fetch.call();
    }
  }

  private GHPullRequest fetchGitHubPullRequestInfo() throws IOException {
    status.update(Code.SYNC, "Fetch GitHub", "Getting PullRequest info");
    GHPullRequest pr = getGHRepository().getPullRequest(prId);
    return pr;
  }

  @Override
  public GitJobStatus getStatus() {
    return status;
  }

  @Override
  public int getIndex() {
    return jobIndex;
  }

  @Override
  public String getOrganisation() {
    return organisation;
  }

  public GHRepository getGHRepository() throws IOException {
    if (ghLogin.getMyself().getLogin().equals(organisation)) {
      return ghLogin.getMyself().getRepository(repoName);
    }
    return ghLogin.getHub().getOrganization(organisation).getRepository(repoName);
  }

  @Override
  public void cancel() {
    cancelRequested = true;
  }

  @Override
  public String getRepository() {
    return repoName;
  }

  @Override
  public void beginTask(String taskName, int numSteps) {
    status.update(Code.SYNC, taskName, taskName + " ...");
  }

  @Override
  public void endTask() {}

  @Override
  public boolean isCancelled() {
    return cancelRequested;
  }

  @Override
  public void start(int tot) {}

  @Override
  public void update(int progress) {}
}
