// Copyright (C) 2022 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.server.restapi.change;

import static com.google.gerrit.server.notedb.ChangeNoteFooters.FOOTER_CHANGE_ID;
import static com.google.gerrit.server.project.ProjectCache.illegalState;
import static com.google.gerrit.server.update.context.RefUpdateContext.RefUpdateType.CHANGE_MODIFICATION;

import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.gerrit.entities.BooleanProjectConfig;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.Project.NameKey;
import com.google.gerrit.extensions.api.changes.ApplyPatchPatchSetInput;
import com.google.gerrit.extensions.client.ListChangesOption;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.PreconditionFailedException;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.change.ChangeJson;
import com.google.gerrit.server.change.ChangeResource;
import com.google.gerrit.server.change.PatchSetInserter;
import com.google.gerrit.server.git.CodeReviewCommit;
import com.google.gerrit.server.git.CodeReviewCommit.CodeReviewRevWalk;
import com.google.gerrit.server.git.CommitUtil;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.project.ContributorAgreementsChecker;
import com.google.gerrit.server.project.InvalidChangeOperationException;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.project.NoSuchProjectException;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.query.change.ChangeData;
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.update.context.RefUpdateContext;
import com.google.gerrit.server.util.time.TimeUtil;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import java.time.Instant;
import java.time.ZoneId;
import java.util.List;
import java.util.Optional;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.patch.PatchApplier;
import org.eclipse.jgit.revwalk.FooterLine;
import org.eclipse.jgit.revwalk.RevCommit;

@Singleton
public class ApplyPatch implements RestModifyView<ChangeResource, ApplyPatchPatchSetInput> {
  private final ChangeJson.Factory jsonFactory;
  private final ContributorAgreementsChecker contributorAgreements;
  private final Provider<IdentifiedUser> user;
  private final GitRepositoryManager gitManager;
  private final BatchUpdate.Factory batchUpdateFactory;
  private final PatchSetInserter.Factory patchSetInserterFactory;
  private final Provider<InternalChangeQuery> queryProvider;
  private final ZoneId serverZoneId;
  private final ProjectCache projectCache;
  private final ChangeUtil changeUtil;

  @Inject
  ApplyPatch(
      ChangeJson.Factory jsonFactory,
      ContributorAgreementsChecker contributorAgreements,
      Provider<IdentifiedUser> user,
      GitRepositoryManager gitManager,
      BatchUpdate.Factory batchUpdateFactory,
      PatchSetInserter.Factory patchSetInserterFactory,
      Provider<InternalChangeQuery> queryProvider,
      @GerritPersonIdent PersonIdent myIdent,
      ProjectCache projectCache,
      ChangeUtil changeUtil) {
    this.jsonFactory = jsonFactory;
    this.contributorAgreements = contributorAgreements;
    this.user = user;
    this.gitManager = gitManager;
    this.batchUpdateFactory = batchUpdateFactory;
    this.patchSetInserterFactory = patchSetInserterFactory;
    this.queryProvider = queryProvider;
    this.serverZoneId = myIdent.getZoneId();
    this.projectCache = projectCache;
    this.changeUtil = changeUtil;
  }

  @Override
  public Response<ChangeInfo> apply(ChangeResource rsrc, ApplyPatchPatchSetInput input)
      throws IOException, UpdateException, RestApiException, PermissionBackendException,
          ConfigInvalidException, NoSuchProjectException, InvalidChangeOperationException {
    NameKey project = rsrc.getProject();
    contributorAgreements.check(project, rsrc.getUser());
    BranchNameKey destBranch = rsrc.getChange().getDest();

    if (input == null || input.patch == null || input.patch.patch == null) {
      throw new BadRequestException("patch required");
    }

    try (Repository repo = gitManager.openRepository(project);
        // This inserter and revwalk *must* be passed to any BatchUpdates
        // created later on, to ensure the applied commit is flushed
        // before patch sets are updated.
        ObjectInserter oi = repo.newObjectInserter();
        ObjectReader reader = oi.newReader();
        CodeReviewRevWalk revWalk = CodeReviewCommit.newRevWalk(reader)) {
      Ref destRef = repo.getRefDatabase().exactRef(destBranch.branch());
      if (destRef == null) {
        throw new ResourceNotFoundException(
            String.format("Branch %s does not exist.", destBranch.branch()));
      }
      ChangeData destChange = rsrc.getChangeData();
      if (destChange == null) {
        throw new PreconditionFailedException(
            "patch:apply cannot be called without a destination change.");
      }

      if (destChange.change().isClosed()) {
        throw new PreconditionFailedException(
            String.format(
                "patch:apply with Change-Id %s could not update the existing change %d "
                    + "in destination branch %s of project %s, because the change was closed (%s)",
                destChange.getId(),
                destChange.getId().get(),
                destBranch.branch(),
                destBranch.project(),
                destChange.change().getStatus().name()));
      }

      if (!Strings.isNullOrEmpty(input.base) && Boolean.TRUE.equals(input.amend)) {
        throw new BadRequestException("amend only works with existing revisions. omit base.");
      }

      RevCommit latestPatchset = revWalk.parseCommit(destChange.currentPatchSet().commitId());
      RevCommit baseCommit;
      ImmutableList<RevCommit> parents;
      if (!Strings.isNullOrEmpty(input.base)) {
        baseCommit =
            CommitUtil.getBaseCommit(
                project.get(), queryProvider.get(), revWalk, destRef, input.base);
        parents = ImmutableList.of(baseCommit);
      } else {
        if (latestPatchset.getParentCount() != 1) {
          throw new BadRequestException(
              String.format(
                  "Cannot parse base commit for a change with none or multiple parents. Change ID: %s.",
                  destChange.getId()));
        }
        if (Boolean.TRUE.equals(input.amend)) {
          baseCommit = latestPatchset;
          parents = ImmutableList.copyOf(baseCommit.getParents());
        } else {
          baseCommit = revWalk.parseCommit(latestPatchset.getParent(0));
          parents = ImmutableList.of(baseCommit);
        }
      }
      PatchApplier.Result applyResult =
          ApplyPatchUtil.applyPatch(repo, oi, input.patch, baseCommit);
      ObjectId treeId = applyResult.getTreeId();

      Instant now = TimeUtil.now();
      PersonIdent committerIdent =
          Optional.ofNullable(latestPatchset.getCommitterIdent())
              .map(
                  ident ->
                      user.get()
                          .newCommitterIdent(ident.getEmailAddress(), now, serverZoneId)
                          .orElseGet(() -> user.get().newCommitterIdent(now, serverZoneId)))
              .orElseGet(() -> user.get().newCommitterIdent(now, serverZoneId));
      PersonIdent authorIdent =
          input.author == null
              ? committerIdent
              : new PersonIdent(input.author.name, input.author.email, now, serverZoneId);
      String commitMessage =
          buildFullCommitMessage(
              project,
              latestPatchset,
              input,
              ApplyPatchUtil.getResultPatch(repo, reader, baseCommit, revWalk.lookupTree(treeId)),
              applyResult.getErrors());

      ObjectId appliedCommit =
          CommitUtil.createCommitWithTree(
              oi, authorIdent, committerIdent, parents, commitMessage, treeId);
      CodeReviewCommit commit = revWalk.parseCommit(appliedCommit);
      oi.flush();

      Change resultChange;
      try (BatchUpdate bu = batchUpdateFactory.create(project, user.get(), TimeUtil.now())) {
        bu.setRepository(repo, revWalk, oi);
        resultChange =
            insertPatchSet(bu, repo, patchSetInserterFactory, destChange.notes(), commit);
      } catch (NoSuchChangeException | RepositoryNotFoundException e) {
        throw new ResourceConflictException(e.getMessage());
      }
      List<ListChangesOption> opts = input.responseFormatOptions;
      if (opts == null) {
        opts = ImmutableList.of();
      }
      ChangeInfo changeInfo = jsonFactory.create(opts).format(resultChange);
      return Response.ok(changeInfo);
    }
  }

  private String buildFullCommitMessage(
      NameKey project,
      RevCommit latestPatchset,
      ApplyPatchPatchSetInput input,
      String resultPatch,
      List<org.eclipse.jgit.patch.PatchApplier.Result.Error> errors)
      throws ResourceConflictException, BadRequestException {
    boolean hasInputCommitMessage = !Strings.isNullOrEmpty(input.commitMessage);
    String fullMessage =
        hasInputCommitMessage ? input.commitMessage : latestPatchset.getFullMessage();
    // Since we might add error information to the message, we need to split the footers from the
    // actual description.
    // TODO: Fix parsing footers from the commit message. FooterLine#fromMessage expects the raw
    // commit message that contains header lines, see RawParseUtils#commitMessage which is invoked
    // from FooterLine#fromMessage. RawParseUtils#commitMessage always increases the pointer by 46
    // to skip the "tree ..." line and if this line is not present the parsing of the footers is
    // broken. This can lead to no footers being found although a Change-Id footer is present. This
    // causes us to add the Change-Id again and as a result we end up with a commit message that
    // contains the Change-Id line twice.
    List<FooterLine> footerLines = FooterLine.fromMessage(fullMessage);
    String messageWithNoFooters = removeFooters(fullMessage, footerLines);
    if (FooterLine.getValues(footerLines, FOOTER_CHANGE_ID).isEmpty()) {
      footerLines.add(
          latestPatchset.getFooterLines().stream()
              .filter(f -> f.matches(FOOTER_CHANGE_ID))
              .findFirst()
              .get());
    }
    String commitMessage =
        ApplyPatchUtil.buildCommitMessage(
            messageWithNoFooters, footerLines, input.patch.patch, resultPatch, errors);

    boolean changeIdRequired =
        projectCache
            .get(project)
            .orElseThrow(illegalState(project))
            .is(BooleanProjectConfig.REQUIRE_CHANGE_ID);
    changeUtil.ensureChangeIdIsCorrect(
        changeIdRequired, changeUtil.getChangeIdsFromFooter(latestPatchset).get(0), commitMessage);

    return commitMessage;
  }

  private static Change insertPatchSet(
      BatchUpdate bu,
      Repository git,
      PatchSetInserter.Factory patchSetInserterFactory,
      ChangeNotes destNotes,
      CodeReviewCommit commit)
      throws IOException, UpdateException, RestApiException {
    try (RefUpdateContext ctx = RefUpdateContext.open(CHANGE_MODIFICATION)) {
      Change destChange = destNotes.getChange();
      PatchSet.Id psId = ChangeUtil.nextPatchSetId(git, destChange.currentPatchSetId());
      PatchSetInserter inserter = patchSetInserterFactory.create(destNotes, psId, commit);
      inserter.setMessage(buildMessageForPatchSet(psId));
      bu.addOp(destChange.getId(), inserter);
      bu.execute();
      return inserter.getChange();
    }
  }

  private static String buildMessageForPatchSet(PatchSet.Id psId) {
    return new StringBuilder(String.format("Uploaded patch set %s.", psId.get())).toString();
  }

  private String removeFooters(String originalMessage, List<FooterLine> footerLines) {
    if (footerLines.isEmpty()) {
      return originalMessage;
    }
    return originalMessage.substring(0, originalMessage.indexOf(footerLines.get(0).getKey()));
  }
}
