// Copyright (C) 2012 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.gerrit.entities.Account;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.Project;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.index.query.QueryResult;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.IdentifiedUser.GenericFactory;
import com.google.gerrit.server.change.ChangeInserter;
import com.google.gerrit.server.change.PatchSetInserter;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.Sequences;
import com.google.gerrit.server.project.InvalidChangeOperationException;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.ChangeQueryBuilder;
import com.google.gerrit.server.query.change.ChangeQueryProcessor;
import com.google.gerrit.server.query.change.InternalChangeQuery;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.update.UpdateException;
import com.google.gerrit.server.util.time.TimeUtil;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.io.IOException;
import java.time.Instant;
import java.util.Collections;
import java.util.List;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.FooterKey;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.util.ChangeIdUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class PullRequestCreateChange {
  private static final Logger LOG = LoggerFactory.getLogger(PullRequestCreateChange.class);
  private static final FooterKey CHANGE_ID = new FooterKey("Change-Id");

  private final ChangeInserter.Factory changeInserterFactory;
  private final PatchSetInserter.Factory patchSetInserterFactory;
  private final GenericFactory userFactory;
  private final Provider<InternalChangeQuery> queryProvider;
  private final BatchUpdate.Factory updateFactory;
  private final Provider<ChangeQueryProcessor> qp;
  private final ChangeQueryBuilder changeQuery;
  private final Sequences sequences;

  @Inject
  PullRequestCreateChange(
      ChangeInserter.Factory changeInserterFactory,
      PatchSetInserter.Factory patchSetInserterFactory,
      IdentifiedUser.GenericFactory userFactory,
      Provider<InternalChangeQuery> queryProvider,
      BatchUpdate.Factory batchUpdateFactory,
      Provider<ChangeQueryProcessor> qp,
      ChangeQueryBuilder changeQuery,
      Sequences sequences) {
    this.changeInserterFactory = changeInserterFactory;
    this.patchSetInserterFactory = patchSetInserterFactory;
    this.userFactory = userFactory;
    this.queryProvider = queryProvider;
    this.updateFactory = batchUpdateFactory;
    this.qp = qp;
    this.changeQuery = changeQuery;
    this.sequences = sequences;
  }

  public Change.Id addCommitToChange(
      final Project project,
      final Repository repo,
      final String destinationBranch,
      final Account.Id pullRequestOwner,
      final RevCommit pullRequestCommit,
      final String pullRequestMessage,
      final String topic)
      throws NoSuchChangeException, IOException, InvalidChangeOperationException, UpdateException,
          RestApiException {
    try (BatchUpdate bu =
        updateFactory.create(
            project.getNameKey(),
            userFactory.create(pullRequestOwner),
            Instant.now())) {

      return internalAddCommitToChange(
          bu,
          project,
          repo,
          destinationBranch,
          pullRequestOwner,
          pullRequestCommit,
          pullRequestMessage,
          topic);
    }
  }

  public Change.Id internalAddCommitToChange(
      BatchUpdate bu,
      final Project project,
      final Repository repo,
      final String destinationBranch,
      final Account.Id pullRequestOwner,
      final RevCommit pullRequestCommit,
      final String pullRequestMesage,
      final String topic)
      throws InvalidChangeOperationException, IOException, UpdateException, RestApiException {
    if (destinationBranch == null || destinationBranch.length() == 0) {
      throw new InvalidChangeOperationException("Destination branch cannot be null or empty");
    }
    Ref destRef = repo.findRef(destinationBranch);
    if (destRef == null) {
      throw new InvalidChangeOperationException("Branch " + destinationBranch + " does not exist.");
    }

    String pullRequestSha1 = pullRequestCommit.getId().getName();
    List<ChangeData> existingChanges = queryChangesForSha1(pullRequestSha1);
    if (!existingChanges.isEmpty()) {
      LOG.debug(
          "Pull request commit ID "
              + pullRequestSha1
              + " has been already uploaded as Change-Id="
              + existingChanges.get(0).getId());
      return null;
    }

    Change.Key changeKey;
    final List<String> idList = pullRequestCommit.getFooterLines(CHANGE_ID);
    if (!idList.isEmpty()) {
      final String idStr = idList.get(idList.size() - 1).trim();
      changeKey = Change.key(idStr);
    } else {
      final ObjectId computedChangeId =
          ChangeIdUtil.computeChangeId(
              pullRequestCommit.getTree(),
              pullRequestCommit,
              pullRequestCommit.getAuthorIdent(),
              pullRequestCommit.getCommitterIdent(),
              pullRequestMesage);

      changeKey = Change.key("I" + computedChangeId.name());
    }

    String branchName = destRef.getName();
    List<ChangeData> destChanges =
        queryProvider
            .get()
            .byBranchKey(
                BranchNameKey.create(
                    project.getNameKey(),
                    branchName.startsWith(REFS_HEADS)
                        ? branchName.substring(REFS_HEADS.length())
                        : branchName),
                changeKey);

    if (destChanges.size() > 1) {
      throw new InvalidChangeOperationException(
          "Multiple Changes with Change-ID "
              + changeKey
              + " already exist on the target branch: cannot add a new patch-set "
              + destinationBranch);
    }

    if (destChanges.size() == 1) {
      // The change key exists on the destination branch: adding a new
      // patch-set
      ChangeData destChangeData = destChanges.get(0);
      Change destChange = destChangeData.change();
      insertPatchSet(
          bu, repo, destChange, pullRequestCommit, destChangeData.notes(), pullRequestMesage);
      return destChange.getId();
    }

    // Change key not found on destination branch. We can create a new
    // change.
    return createNewChange(
        bu,
        changeKey,
        project.getNameKey(),
        destRef,
        pullRequestOwner,
        pullRequestCommit,
        destinationBranch,
        pullRequestMesage,
        topic);
  }

  private List<ChangeData> queryChangesForSha1(String pullRequestSha1) {
    QueryResult<ChangeData> results;
    try {
      results = qp.get().query(changeQuery.commit(pullRequestSha1));
      return results.entities();
    } catch (QueryParseException e) {
      LOG.error(
          "Invalid SHA1 " + pullRequestSha1 + ": cannot query changes for this pull request", e);
      return Collections.emptyList();
    }
  }

  private void insertPatchSet(
      BatchUpdate bu,
      Repository git,
      Change change,
      RevCommit cherryPickCommit,
      ChangeNotes changeNotes,
      String pullRequestMessage)
      throws IOException, UpdateException, RestApiException {
    try (RevWalk revWalk = new RevWalk(git)) {
      PatchSet.Id psId = ChangeUtil.nextPatchSetId(git, change.currentPatchSetId());

      PatchSetInserter patchSetInserter =
          patchSetInserterFactory.create(changeNotes, psId, cherryPickCommit);
      patchSetInserter.setMessage(pullRequestMessage);
      patchSetInserter.setValidate(false);

      bu.addOp(change.getId(), patchSetInserter);
      bu.execute();
    }
  }

  private Change.Id createNewChange(
      BatchUpdate bu,
      Change.Key changeKey,
      Project.NameKey project,
      Ref destRef,
      Account.Id pullRequestOwner,
      RevCommit pullRequestCommit,
      String refName,
      String pullRequestMessage,
      String topic)
      throws UpdateException, RestApiException, IOException {
    Change change =
        new Change(
            changeKey,
            Change.id(sequences.nextChangeId()),
            pullRequestOwner,
            BranchNameKey.create(project, destRef.getName()),
            Instant.now());
    if (topic != null) {
      change.setTopic(topic);
    }
    ChangeInserter ins = changeInserterFactory.create(change.getId(), pullRequestCommit, refName);

    ins.setMessage(pullRequestMessage);
    bu.insertChange(ins);
    bu.execute();

    return ins.getChange().getId();
  }
}
