// 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.google.gerrit.server.query.change;

import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.flogger.LazyArgs.lazy;
import static com.google.gerrit.server.project.ProjectCache.noSuchProject;
import static java.util.concurrent.TimeUnit.MINUTES;

import com.google.common.flogger.FluentLogger;
import com.google.common.util.concurrent.UncheckedExecutionException;
import com.google.gerrit.entities.BooleanProjectConfig;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.SubmitTypeRecord;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.index.query.PostFilterPredicate;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.server.git.CodeReviewCommit;
import com.google.gerrit.server.project.NoSuchProjectException;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.query.change.ChangeQueryBuilder.Arguments;
import com.google.gerrit.server.submit.SubmitDryRun;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;

public class ConflictsPredicate {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  // UI code may depend on this string, so use caution when changing.
  protected static final String TOO_MANY_FILES = "too many files to find conflicts";

  private ConflictsPredicate() {}

  public static Predicate<ChangeData> create(Arguments args, String value, Change c)
      throws QueryParseException {
    ChangeData cd;
    List<String> files;
    try {
      cd = args.changeDataFactory.create(c);
      files = cd.currentFilePaths();
    } catch (StorageException e) {
      warnWithOccasionalStackTrace(
          e,
          "Error constructing conflicts predicates for change %s in %s",
          c.getId(),
          c.getProject());
      return ChangeIndexPredicate.none();
    }

    if (3 + files.size() > args.indexConfig.maxTerms()) {
      // Short-circuit with a nice error message if we exceed the index
      // backend's term limit. This assumes that "conflicts:foo" is the entire
      // query; if there are more terms in the input, we might not
      // short-circuit here, which will result in a more generic error message
      // later on in the query parsing.
      throw new QueryParseException(TOO_MANY_FILES);
    }

    List<Predicate<ChangeData>> filePredicates = new ArrayList<>(files.size());
    for (String file : files) {
      filePredicates.add(ChangePredicates.path(file));
    }

    List<Predicate<ChangeData>> and = new ArrayList<>(5);
    and.add(ChangePredicates.project(c.getProject()));
    and.add(ChangePredicates.ref(c.getDest().branch()));
    and.add(Predicate.not(ChangePredicates.idStr(c.getId())));
    and.add(Predicate.or(filePredicates));

    ChangeDataCache changeDataCache = new ChangeDataCache(cd, args.projectCache);
    and.add(new CheckConflict(value, args, c, changeDataCache));
    return Predicate.and(and);
  }

  private static final class CheckConflict extends PostFilterPredicate<ChangeData> {
    private final Arguments args;
    private final BranchNameKey dest;
    private final ChangeDataCache changeDataCache;

    CheckConflict(String value, Arguments args, Change c, ChangeDataCache changeDataCache) {
      super(ChangeQueryBuilder.FIELD_CONFLICTS, value);
      this.args = args;
      this.dest = c.getDest();
      this.changeDataCache = changeDataCache;
    }

    @Override
    public boolean match(ChangeData object) {
      Change.Id id = object.getId();
      Project.NameKey otherProject = null;
      ObjectId other = null;
      try {
        Change otherChange = object.change();
        if (otherChange == null || !otherChange.getDest().equals(dest)) {
          return false;
        }
        otherProject = otherChange.getProject();

        SubmitTypeRecord str = object.submitTypeRecord();
        if (!str.isOk()) {
          return false;
        }

        ProjectState projectState;
        try {
          projectState = changeDataCache.getProjectState();
        } catch (NoSuchProjectException e) {
          return false;
        }

        other = object.currentPatchSet().commitId();
        ConflictKey conflictsKey =
            ConflictKey.create(
                changeDataCache.getTestAgainst(),
                other,
                str.type,
                projectState.is(BooleanProjectConfig.USE_CONTENT_MERGE));
        return args.conflictsCache.get(conflictsKey, new Loader(object, changeDataCache, args));
      } catch (StorageException | ExecutionException | UncheckedExecutionException e) {
        ObjectId finalOther = other;
        warnWithOccasionalStackTrace(
            e,
            "Merge failure checking conflicts of change %s in %s (%s): %s",
            id,
            firstNonNull(otherProject, "unknown project"),
            lazy(() -> finalOther != null ? finalOther.name() : "unknown commit"),
            e.getMessage());
        return false;
      }
    }

    @Override
    public int getCost() {
      return 5;
    }
  }

  static class ChangeDataCache {
    private final ChangeData cd;
    private final ProjectCache projectCache;

    private ObjectId testAgainst;
    private ProjectState projectState;
    private Set<ObjectId> alreadyAccepted;

    ChangeDataCache(ChangeData cd, ProjectCache projectCache) {
      this.cd = cd;
      this.projectCache = projectCache;
    }

    ObjectId getTestAgainst() {
      if (testAgainst == null) {
        testAgainst = cd.currentPatchSet().commitId();
      }
      return testAgainst;
    }

    ProjectState getProjectState() throws NoSuchProjectException {
      if (projectState == null) {
        projectState = projectCache.get(cd.project()).orElseThrow(noSuchProject(cd.project()));
      }
      return projectState;
    }

    Set<ObjectId> getAlreadyAccepted(Repository repo) throws IOException {
      if (alreadyAccepted == null) {
        alreadyAccepted = SubmitDryRun.getAlreadyAccepted(repo);
      }
      return alreadyAccepted;
    }
  }

  private static void warnWithOccasionalStackTrace(Throwable cause, String format, Object... args) {
    logger.atWarning().logVarargs(format, args);
    logger
        .atWarning()
        .withCause(cause)
        .atMostEvery(1, MINUTES)
        .logVarargs("(Re-logging with stack trace) " + format, args);
  }

  private static class Loader implements Callable<Boolean> {
    private final ChangeData changeData;
    private final ConflictsPredicate.ChangeDataCache changeDataCache;
    private final ChangeQueryBuilder.Arguments args;

    private Loader(
        ChangeData changeData,
        ConflictsPredicate.ChangeDataCache changeDataCache,
        ChangeQueryBuilder.Arguments args) {
      this.changeData = changeData;
      this.changeDataCache = changeDataCache;
      this.args = args;
    }

    @Override
    public Boolean call() throws Exception {
      Change otherChange = changeData.change();
      ObjectId other = changeData.currentPatchSet().commitId();
      try (Repository repo = args.repoManager.openRepository(otherChange.getProject());
          CodeReviewCommit.CodeReviewRevWalk rw = CodeReviewCommit.newRevWalk(repo)) {
        return !args.submitDryRun.run(
            null,
            changeData.submitTypeRecord().type,
            repo,
            rw,
            otherChange.getDest(),
            changeDataCache.getTestAgainst(),
            other,
            getAlreadyAccepted(repo, rw));
      } catch (NoSuchProjectException | IOException e) {
        warnWithOccasionalStackTrace(
            e,
            "Failure when loading conflicts of change %s in %s (%s): %s",
            lazy(changeData::getId),
            lazy(() -> firstNonNull(otherChange.getProject(), "unknown project")),
            lazy(() -> other != null ? other.name() : "unknown commit"),
            e.getMessage());
        return false;
      }
    }

    private Set<RevCommit> getAlreadyAccepted(Repository repo, RevWalk rw) {
      try {
        Set<RevCommit> accepted = new HashSet<>();
        SubmitDryRun.addCommits(changeDataCache.getAlreadyAccepted(repo), rw, accepted);
        ObjectId tip = changeDataCache.getTestAgainst();
        if (tip != null) {
          accepted.add(rw.parseCommit(tip));
        }
        return accepted;
      } catch (StorageException | IOException e) {
        throw new StorageException("Failed to determine already accepted commits.", e);
      }
    }
  }
}
