// 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;
      List<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.
    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()));
  }
}
