// 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 com.google.common.collect.Lists;
import com.google.gerrit.common.data.SubmitTypeRecord;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.git.CodeReviewCommit;
import com.google.gerrit.server.git.CodeReviewCommit.CodeReviewRevWalk;
import com.google.gerrit.server.git.IntegrationException;
import com.google.gerrit.server.git.strategy.SubmitDryRun;
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.OrPredicate;
import com.google.gerrit.server.query.Predicate;
import com.google.gerrit.server.query.QueryParseException;
import com.google.gerrit.server.query.change.ChangeQueryBuilder.Arguments;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Provider;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.revwalk.filter.RevFilter;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.filter.TreeFilter;

class ConflictsPredicate extends OrPredicate<ChangeData> {
  // UI code may depend on this string, so use caution when changing.
  private static final String TOO_MANY_FILES = "too many files to find conflicts";

  private final String value;

  ConflictsPredicate(Arguments args, String value, List<Change> changes)
      throws QueryParseException, OrmException {
    super(predicates(args, value, changes));
    this.value = value;
  }

  private static List<Predicate<ChangeData>> predicates(
      final Arguments args, String value, List<Change> changes)
      throws QueryParseException, OrmException {
    int indexTerms = 0;

    List<Predicate<ChangeData>> changePredicates = Lists.newArrayListWithCapacity(changes.size());
    final Provider<ReviewDb> db = args.db;
    for (final Change c : changes) {
      final ChangeDataCache changeDataCache =
          new ChangeDataCache(c, db, args.changeDataFactory, args.projectCache);
      List<String> files = listFiles(c, args, changeDataCache);
      indexTerms += 3 + files.size();
      if (indexTerms > 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 = Lists.newArrayListWithCapacity(files.size());
      for (String file : files) {
        filePredicates.add(new EqualsPathPredicate(ChangeQueryBuilder.FIELD_PATH, file));
      }

      List<Predicate<ChangeData>> predicatesForOneChange = Lists.newArrayListWithCapacity(5);
      predicatesForOneChange.add(not(new LegacyChangeIdPredicate(c.getId())));
      predicatesForOneChange.add(new ProjectPredicate(c.getProject().get()));
      predicatesForOneChange.add(new RefPredicate(c.getDest().get()));

      predicatesForOneChange.add(or(or(filePredicates), new IsMergePredicate(args, value)));

      predicatesForOneChange.add(
          new ChangeOperatorPredicate(ChangeQueryBuilder.FIELD_CONFLICTS, value) {

            @Override
            public boolean match(ChangeData object) throws OrmException {
              Change otherChange = object.change();
              if (otherChange == null) {
                return false;
              }
              if (!otherChange.getDest().equals(c.getDest())) {
                return false;
              }
              SubmitTypeRecord str = object.submitTypeRecord();
              if (!str.isOk()) {
                return false;
              }
              ObjectId other = ObjectId.fromString(object.currentPatchSet().getRevision().get());
              ConflictKey conflictsKey =
                  new ConflictKey(
                      changeDataCache.getTestAgainst(),
                      other,
                      str.type,
                      changeDataCache.getProjectState().isUseContentMerge());
              Boolean conflicts = args.conflictsCache.getIfPresent(conflictsKey);
              if (conflicts != null) {
                return conflicts;
              }
              try (Repository repo = args.repoManager.openRepository(otherChange.getProject());
                  CodeReviewRevWalk rw = CodeReviewCommit.newRevWalk(repo)) {
                conflicts =
                    !args.submitDryRun.run(
                        str.type,
                        repo,
                        rw,
                        otherChange.getDest(),
                        changeDataCache.getTestAgainst(),
                        other,
                        getAlreadyAccepted(repo, rw));
                args.conflictsCache.put(conflictsKey, conflicts);
                return conflicts;
              } catch (IntegrationException | NoSuchProjectException | IOException e) {
                throw new OrmException(e);
              }
            }

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

            private Set<RevCommit> getAlreadyAccepted(Repository repo, RevWalk rw)
                throws IntegrationException {
              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 (OrmException | IOException e) {
                throw new IntegrationException("Failed to determine already accepted commits.", e);
              }
            }
          });
      changePredicates.add(and(predicatesForOneChange));
    }
    return changePredicates;
  }

  private static List<String> listFiles(Change c, Arguments args, ChangeDataCache changeDataCache)
      throws OrmException {
    try (Repository repo = args.repoManager.openRepository(c.getProject());
        RevWalk rw = new RevWalk(repo)) {
      RevCommit ps = rw.parseCommit(changeDataCache.getTestAgainst());
      if (ps.getParentCount() > 1) {
        String dest = c.getDest().get();
        Ref destBranch = repo.getRefDatabase().getRef(dest);
        destBranch.getObjectId();
        rw.setRevFilter(RevFilter.MERGE_BASE);
        rw.markStart(rw.parseCommit(destBranch.getObjectId()));
        rw.markStart(ps);
        RevCommit base = rw.next();
        // TODO(zivkov): handle the case with multiple merge bases

        List<String> files = new ArrayList<>();
        try (TreeWalk tw = new TreeWalk(repo)) {
          if (base != null) {
            tw.setFilter(TreeFilter.ANY_DIFF);
            tw.addTree(base.getTree());
          }
          tw.addTree(ps.getTree());
          tw.setRecursive(true);
          while (tw.next()) {
            files.add(tw.getPathString());
          }
        }
        return files;
      }
      return args.changeDataFactory.create(args.db.get(), c).currentFilePaths();
    } catch (IOException e) {
      throw new OrmException(e);
    }
  }

  @Override
  public String toString() {
    return ChangeQueryBuilder.FIELD_CONFLICTS + ":" + value;
  }

  private static class ChangeDataCache {
    private final Change change;
    private final Provider<ReviewDb> db;
    private final ChangeData.Factory changeDataFactory;
    private final ProjectCache projectCache;

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

    ChangeDataCache(
        Change change,
        Provider<ReviewDb> db,
        ChangeData.Factory changeDataFactory,
        ProjectCache projectCache) {
      this.change = change;
      this.db = db;
      this.changeDataFactory = changeDataFactory;
      this.projectCache = projectCache;
    }

    ObjectId getTestAgainst() throws OrmException {
      if (testAgainst == null) {
        testAgainst =
            ObjectId.fromString(
                changeDataFactory.create(db.get(), change).currentPatchSet().getRevision().get());
      }
      return testAgainst;
    }

    ProjectState getProjectState() {
      if (projectState == null) {
        projectState = projectCache.get(change.getProject());
        if (projectState == null) {
          throw new IllegalStateException(new NoSuchProjectException(change.getProject()));
        }
      }
      return projectState;
    }

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