// 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.entities.RefNames.REFS_HEADS;

import com.google.common.collect.Lists;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Change.Id;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.Project.NameKey;
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.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 Optional<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 Optional<Project> fetchGerritProject(
      ProjectCache projectCache, String fetchOrganisation, String fetchRepoName) {
    NameKey projectNameKey = Project.NameKey.parse(fetchOrganisation + "/" + fetchRepoName);
    return projectCache.get(projectNameKey).map(ProjectState::getProject);
  }

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

      exitWhenCancelled();
      try (Repository gitRepo =
          repoMgr.openRepository(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);
        if (project.isPresent()) {
          Id changeId =
              createChange.addCommitToChange(
                  project.get(),
                  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.entities.Account.Id getOrRegisterAccount(GitHubUser author)
      throws BadRequestException, ResourceConflictException, UnprocessableEntityException,
          IOException, ConfigInvalidException {
    return getOrRegisterAccount(author.getLogin(), author.getName(), author.getEmail());
  }

  private com.google.gerrit.entities.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) {}
}
