// 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.notedb;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.gerrit.entities.RefNames.changeMetaRef;
import static java.util.Comparator.comparing;

import com.google.auto.value.AutoValue;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Ordering;
import com.google.common.flogger.FluentLogger;
import com.google.errorprone.annotations.FormatMethod;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.UsedAt;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.AttentionSetUpdate;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.ChangeMessage;
import com.google.gerrit.entities.Comment;
import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.PatchSetApproval;
import com.google.gerrit.entities.PatchSetApprovals;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.entities.SubmitRecord;
import com.google.gerrit.entities.SubmitRequirementResult;
import com.google.gerrit.server.ReviewerByEmailSet;
import com.google.gerrit.server.ReviewerSet;
import com.google.gerrit.server.ReviewerStatusUpdate;
import com.google.gerrit.server.git.RefCache;
import com.google.gerrit.server.project.NoSuchChangeException;
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.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Stream;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;

/** View of a single {@link Change} based on the log of its notes branch. */
// TODO(paiking): This class should be refactored to get rid of potentially duplicate or unneeded
// variables, such as allAttentionSetUpdates, reviewerUpdates, and others.

public class ChangeNotes extends AbstractChangeNotes<ChangeNotes> {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  static final Ordering<PatchSetApproval> PSA_BY_TIME =
      Ordering.from(comparing(PatchSetApproval::granted));

  @FormatMethod
  public static ConfigInvalidException parseException(
      Change.Id changeId, String fmt, Object... args) {
    return new ConfigInvalidException("Change " + changeId + ": " + String.format(fmt, args));
  }

  @Singleton
  public static class Factory {
    private final Args args;
    private final Provider<InternalChangeQuery> queryProvider;
    private final ProjectCache projectCache;

    @VisibleForTesting
    @Inject
    public Factory(
        Args args, Provider<InternalChangeQuery> queryProvider, ProjectCache projectCache) {
      this.args = args;
      this.queryProvider = queryProvider;
      this.projectCache = projectCache;
    }

    public static ImmutableMap<Change.Id, ObjectId> scanChangeIds(Repository repo)
        throws IOException {
      ImmutableMap.Builder<Change.Id, ObjectId> metaIdByChange = ImmutableMap.builder();
      for (Ref r : repo.getRefDatabase().getRefsByPrefix(RefNames.REFS_CHANGES)) {
        if (r.getName().endsWith(RefNames.META_SUFFIX)) {
          Change.Id id = Change.Id.fromRef(r.getName());
          if (id != null) {
            metaIdByChange.put(id, r.getObjectId());
          }
        }
      }
      return metaIdByChange.build();
    }

    public ChangeNotes createChecked(Change c) {
      return createChecked(c.getProject(), c.getId());
    }

    /**
     * Load the change-notes associated to a project/change-id using an existing open repository
     *
     * @param repo existing open repository
     * @param project project associated with the repository
     * @param changeId change-id associated with the change-notes to load
     * @param metaRevId version of the change-id to load, null for loading the latest
     * @return change-notes object for the change
     */
    @UsedAt(UsedAt.Project.MODULE_GIT_REFS_FILTER)
    public ChangeNotes createChecked(
        Repository repo,
        Project.NameKey project,
        Change.Id changeId,
        @Nullable ObjectId metaRevId) {
      Change change = newChange(project, changeId);
      return new ChangeNotes(args, change, true, null, metaRevId).load(repo);
    }

    public ChangeNotes createChecked(
        Project.NameKey project, Change.Id changeId, @Nullable ObjectId metaRevId) {
      Change change = newChange(project, changeId);
      return new ChangeNotes(args, change, true, null, metaRevId).load();
    }

    public ChangeNotes createChecked(Project.NameKey project, Change.Id changeId) {
      return createChecked(project, changeId, null);
    }

    public static Change newChange(Project.NameKey project, Change.Id changeId) {
      return new Change(
          null, changeId, null, BranchNameKey.create(project, "INVALID_NOTE_DB_ONLY"), null);
    }

    public ChangeNotes create(Project.NameKey project, Change.Id changeId) {
      checkArgument(project != null, "project is required");
      return new ChangeNotes(args, newChange(project, changeId), true, null).load();
    }

    public ChangeNotes create(
        Project.NameKey project, Change.Id changeId, @Nullable ObjectId metaRevId) {
      checkArgument(project != null, "project is required");
      return new ChangeNotes(args, newChange(project, changeId), true, null, metaRevId).load();
    }

    public ChangeNotes create(Repository repository, Project.NameKey project, Change.Id changeId) {
      checkArgument(project != null, "project is required");
      return new ChangeNotes(args, newChange(project, changeId), true, null).load(repository);
    }

    /**
     * Create change notes for a change that was loaded from index. This method should only be used
     * when database access is harmful and potentially stale data from the index is acceptable.
     *
     * @param change change loaded from secondary index
     * @return change notes
     */
    public ChangeNotes createFromIndexedChange(Change change) {
      return new ChangeNotes(args, change, true, null);
    }

    public ChangeNotes createForBatchUpdate(Change change, boolean shouldExist) {
      return new ChangeNotes(args, change, shouldExist, null).load();
    }

    public ChangeNotes create(Change change, RefCache refs) {
      return new ChangeNotes(args, change, true, refs).load();
    }

    /**
     * Create change notes based on a {@link com.google.gerrit.entities.Change.Id}. This requires
     * using the Change index and should only be used when {@link
     * com.google.gerrit.entities.Project.NameKey} and the numeric change ID are not available.
     */
    public ChangeNotes createCheckedUsingIndexLookup(Change.Id changeId) {
      InternalChangeQuery query = queryProvider.get().setLimit(2).noFields();
      List<ChangeData> changes = query.byLegacyChangeId(changeId);
      if (changes.isEmpty()) {
        throw new NoSuchChangeException(changeId);
      }
      if (changes.size() != 1) {
        logger.atSevere().log("Multiple changes found for %d", changeId.get());
        throw new NoSuchChangeException(changeId);
      }
      return changes.get(0).notes();
    }

    /**
     * Create change notes based on a list of {@link com.google.gerrit.entities.Change.Id}s. This
     * requires using the Change index and should only be used when {@link
     * com.google.gerrit.entities.Project.NameKey} and the numeric change ID are not available.
     */
    @UsedAt(UsedAt.Project.PLUGINS_ALL)
    @Deprecated(since = "3.10", forRemoval = true)
    public List<ChangeNotes> createUsingIndexLookup(Collection<Change.Id> changeIds) {
      List<ChangeNotes> notes = new ArrayList<>();
      for (Change.Id changeId : changeIds) {
        try {
          notes.add(createCheckedUsingIndexLookup(changeId));
        } catch (NoSuchChangeException e) {
          // Ignore missing changes to match Access#get(Iterable) behavior.
        }
      }
      return notes;
    }

    public List<ChangeNotes> create(
        Repository repo,
        Project.NameKey project,
        Collection<Change.Id> changeIds,
        Predicate<ChangeNotes> predicate) {
      List<ChangeNotes> notes = new ArrayList<>();
      for (Change.Id cid : changeIds) {
        try {
          ChangeNotes cn = create(repo, project, cid);
          if (cn.getChange() != null && predicate.test(cn)) {
            notes.add(cn);
          }
        } catch (NoSuchChangeException e) {
          // Match ReviewDb behavior, returning not found; maybe the caller learned about it from
          // a dangling patch set ref or something.
          continue;
        }
      }
      return notes;
    }

    /* TODO: This is now unused in the Gerrit code-base, however it is kept in the code
    /* because it is a public method in a stable branch.
     * It can be removed in master branch where we have more flexibility to change the API
     * interface.
     */
    public List<ChangeNotes> create(
        Project.NameKey project,
        Collection<Change.Id> changeIds,
        Predicate<ChangeNotes> predicate) {
      try (Repository repo = args.repoManager.openRepository(project)) {
        return create(repo, project, changeIds, predicate);
      } catch (RepositoryNotFoundException e) {
        // The repository does not exist, hence it does not contain
        // any change.
      } catch (IOException e) {
        logger.atWarning().withCause(e).log(
            "Unable to open project=%s when trying to retrieve changeId=%s from NoteDb",
            project, changeIds);
      }
      return Collections.emptyList();
    }

    public ListMultimap<Project.NameKey, ChangeNotes> create(Predicate<ChangeNotes> predicate)
        throws IOException {
      ImmutableListMultimap.Builder<Project.NameKey, ChangeNotes> m =
          ImmutableListMultimap.builder();
      for (Project.NameKey project : projectCache.all()) {
        try (Repository repo = args.repoManager.openRepository(project)) {
          scan(repo, project)
              .filter(r -> !r.error().isPresent())
              .map(ChangeNotesResult::notes)
              .filter(predicate)
              .forEach(n -> m.put(n.getProjectName(), n));
        }
      }
      return m.build();
    }

    public Stream<ChangeNotesResult> scan(Repository repo, Project.NameKey project)
        throws IOException {
      return scan(repo, project, null);
    }

    public Stream<ChangeNotesResult> scan(
        Repository repo, Project.NameKey project, Predicate<Change.Id> changeIdPredicate)
        throws IOException {
      return scan(scanChangeIds(repo), project, changeIdPredicate);
    }

    public Stream<ChangeNotesResult> scan(
        ImmutableMap<Change.Id, ObjectId> metaIdByChange,
        Project.NameKey project,
        Predicate<Change.Id> changeIdPredicate) {
      Stream<Map.Entry<Change.Id, ObjectId>> metaByIdStream = metaIdByChange.entrySet().stream();
      if (changeIdPredicate != null) {
        metaByIdStream = metaByIdStream.filter(e -> changeIdPredicate.test(e.getKey()));
      }
      return metaByIdStream.map(e -> scanOneChange(project, e)).filter(Objects::nonNull);
    }

    @Nullable
    private ChangeNotesResult scanOneChange(
        Project.NameKey project, Map.Entry<Change.Id, ObjectId> metaIdByChangeId) {
      Change.Id id = metaIdByChangeId.getKey();
      // TODO(dborowitz): See discussion in BatchUpdate#newChangeContext.
      try {
        Change change = ChangeNotes.Factory.newChange(project, id);
        logger.atFine().log("adding change %s found in project %s", id, project);
        return toResult(change, metaIdByChangeId.getValue());
      } catch (InvalidServerIdException ise) {
        logger.atWarning().withCause(ise).log(
            "skipping change %d in project %s because of an invalid server id", id.get(), project);
        return null;
      }
    }

    @Nullable
    private ChangeNotesResult toResult(Change rawChangeFromNoteDb, ObjectId metaId) {
      ChangeNotes n = new ChangeNotes(args, rawChangeFromNoteDb, true, null, metaId);
      try {
        n.load();
      } catch (Exception e) {
        return ChangeNotesResult.error(n.getChangeId(), e);
      }
      return ChangeNotesResult.notes(n);
    }

    /** Result of {@link #scan(Repository,Project.NameKey)}. */
    @AutoValue
    public abstract static class ChangeNotesResult {
      static ChangeNotesResult error(Change.Id id, Throwable e) {
        return new AutoValue_ChangeNotes_Factory_ChangeNotesResult(id, Optional.of(e), null);
      }

      static ChangeNotesResult notes(ChangeNotes notes) {
        return new AutoValue_ChangeNotes_Factory_ChangeNotesResult(
            notes.getChangeId(), Optional.empty(), notes);
      }

      /** Change ID that was scanned. */
      public abstract Change.Id id();

      /** Error encountered while loading this change, if any. */
      public abstract Optional<Throwable> error();

      /**
       * Notes loaded for this change.
       *
       * @return notes.
       * @throws IllegalStateException if there was an error loading the change; callers must check
       *     that {@link #error()} is absent before attempting to look up the notes.
       */
      public ChangeNotes notes() {
        checkState(maybeNotes() != null, "no ChangeNotes loaded; check error().isPresent() first");
        return maybeNotes();
      }

      @Nullable
      abstract ChangeNotes maybeNotes();
    }
  }

  private final boolean shouldExist;
  private final RefCache refs;

  private Change change;
  private ChangeNotesState state;

  // Parsed note map state, used by ChangeUpdate to make in-place editing of
  // notes easier.
  RevisionNoteMap<ChangeRevisionNote> revisionNoteMap;

  private DraftCommentNotes draftCommentNotes;

  // Lazy defensive copies of mutable ReviewDb types, to avoid polluting the
  // ChangeNotesCache from handlers.
  private ImmutableSortedMap<String, String> customKeyedValues;
  private ImmutableSortedMap<PatchSet.Id, PatchSet> patchSets;
  private PatchSetApprovals approvals;
  private ImmutableSet<Comment.Key> commentKeys;

  public ChangeNotes(
      Args args,
      Change change,
      boolean shouldExist,
      @Nullable RefCache refs,
      @Nullable ObjectId metaSha1) {
    super(args, change.getId(), metaSha1);
    this.change = new Change(change);
    this.shouldExist = shouldExist;
    this.refs = refs;
  }

  @VisibleForTesting
  public ChangeNotes(Args args, Change change, boolean shouldExist, @Nullable RefCache refs) {
    this(args, change, shouldExist, refs, null);
  }

  public Change getChange() {
    return change;
  }

  public ObjectId getMetaId() {
    return state.metaId();
  }

  public String getServerId() {
    return state.serverId();
  }

  public ImmutableSortedMap<PatchSet.Id, PatchSet> getPatchSets() {
    if (patchSets == null) {
      ImmutableSortedMap.Builder<PatchSet.Id, PatchSet> b = ImmutableSortedMap.naturalOrder();
      b.putAll(state.patchSets());
      patchSets = b.build();
    }
    return patchSets;
  }

  /** Gets the approvals of all patch sets. */
  public PatchSetApprovals getApprovals() {
    if (approvals == null) {
      approvals = PatchSetApprovals.create(ImmutableListMultimap.copyOf(state.approvals()));
    }
    return approvals;
  }

  public ReviewerSet getReviewers() {
    return state.reviewers();
  }

  /** Returns reviewers that do not currently have a Gerrit account and were added by email. */
  public ReviewerByEmailSet getReviewersByEmail() {
    return state.reviewersByEmail();
  }

  /** Returns reviewers that were modified during this change's current WIP phase. */
  public ReviewerSet getPendingReviewers() {
    return state.pendingReviewers();
  }

  /** Returns reviewers by email that were modified during this change's current WIP phase. */
  public ReviewerByEmailSet getPendingReviewersByEmail() {
    return state.pendingReviewersByEmail();
  }

  public ImmutableList<ReviewerStatusUpdate> getReviewerUpdates() {
    return state.reviewerUpdates();
  }

  /** Returns the most recent update (i.e. status) per user. */
  public ImmutableSet<AttentionSetUpdate> getAttentionSet() {
    return state.attentionSet();
  }

  /** Returns all updates for the attention set. */
  public ImmutableList<AttentionSetUpdate> getAttentionSetUpdates() {
    return state.allAttentionSetUpdates();
  }

  /** Returns the key-value pairs that are attached to this change */
  public ImmutableSortedMap<String, String> getCustomKeyedValues() {
    if (customKeyedValues == null) {
      ImmutableSortedMap.Builder<String, String> b = ImmutableSortedMap.naturalOrder();
      b.putAll(state.customKeyedValues());
      customKeyedValues = b.build();
    }
    return customKeyedValues;
  }

  /**
   * Returns the evaluated submit requirements for the change. We only intend to store submit
   * requirements in NoteDb for closed changes. For closed changes, the results represent the state
   * of evaluating submit requirements for this change when it was merged or abandoned.
   *
   * @throws UnsupportedOperationException if submit requirements are requested for an open change.
   */
  public ImmutableList<SubmitRequirementResult> getSubmitRequirementsResult() {
    if (state.columns().status().isOpen()) {
      throw new UnsupportedOperationException(
          String.format(
              "Cannot request stored submit requirements"
                  + " for an open change: project = %s, change ID = %d",
              getProjectName(), state.changeId().get()));
    }
    return state.submitRequirementsResult();
  }

  /** Returns an ImmutableSet of all hashtags for this change sorted in alphabetical order. */
  public ImmutableSet<String> getHashtags() {
    return ImmutableSortedSet.copyOf(state.hashtags());
  }

  /** Returns a list of all users who have ever been a reviewer on this change. */
  public ImmutableList<Account.Id> getAllPastReviewers() {
    return state.allPastReviewers();
  }

  /**
   * Returns submit records stored during the most recent submit; only for changes that were
   * actually submitted.
   */
  public ImmutableList<SubmitRecord> getSubmitRecords() {
    return state.submitRecords();
  }

  /** Returns all change messages, in chronological order, oldest first. */
  public ImmutableList<ChangeMessage> getChangeMessages() {
    return state.changeMessages();
  }

  /** Returns inline comments on each revision. */
  public ImmutableListMultimap<ObjectId, HumanComment> getHumanComments() {
    return state.publishedComments();
  }

  public ImmutableSet<Comment.Key> getCommentKeys() {
    if (commentKeys == null) {
      ImmutableSet.Builder<Comment.Key> b = ImmutableSet.builder();
      for (Comment c : getHumanComments().values()) {
        b.add(new Comment.Key(c.key));
      }
      commentKeys = b.build();
    }
    return commentKeys;
  }

  public int getUpdateCount() {
    return state.updateCount();
  }

  /** Returns {@link Optional} value of time when the change was merged. */
  public Optional<Instant> getMergedOn() {
    return Optional.ofNullable(state.mergedOn());
  }

  public ImmutableList<HumanComment> getDraftComments(Account.Id author) {
    return getDraftComments(author, null, null);
  }

  public ImmutableList<HumanComment> getDraftComments(Account.Id author, @Nullable Ref ref) {
    return getDraftComments(author, null, ref);
  }

  public ImmutableList<HumanComment> getDraftComments(
      Account.Id author, @Nullable Change.Id virtualId) {
    return getDraftComments(author, virtualId, null);
  }

  ImmutableList<HumanComment> getDraftComments(
      Account.Id author, @Nullable Change.Id virtualId, @Nullable Ref ref) {
    loadDraftComments(author, virtualId, ref);
    // Filter out any zombie draft comments. These are drafts that are also in
    // the published map, and arise when the update to All-Users to delete them
    // during the publish operation failed.
    return draftCommentNotes.getComments().stream()
        .filter(d -> !getCommentKeys().contains(d.key))
        .collect(toImmutableList());
  }

  /**
   * If draft comments have already been loaded for this author, then they will not be reloaded.
   * However, this method will load the comments if no draft comments have been loaded or if the
   * caller would like the drafts for another author.
   */
  private void loadDraftComments(
      Account.Id author, @Nullable Change.Id virtualId, @Nullable Ref ref) {
    if (draftCommentNotes == null || !author.equals(draftCommentNotes.getAuthor()) || ref != null) {
      draftCommentNotes = new DraftCommentNotes(args, getChangeId(), virtualId, author, ref);
      draftCommentNotes.load();
    }
  }

  @VisibleForTesting
  DraftCommentNotes getDraftCommentNotes() {
    return draftCommentNotes;
  }

  public boolean containsCommentPublished(Comment c) {
    for (Comment l : getHumanComments().values()) {
      if (c.key.equals(l.key)) {
        return true;
      }
    }
    return false;
  }

  @Override
  public String getRefName() {
    return changeMetaRef(getChangeId());
  }

  public PatchSet getCurrentPatchSet() {
    PatchSet.Id psId = change.currentPatchSetId();
    if (psId == null || getPatchSets().get(psId) == null) {
      // In some cases, the current patch-set doesn't exist yet as it's being created during the
      // operation (e.g rebase).
      PatchSet currentPatchset =
          getPatchSets().values().stream()
              .max((p1, p2) -> p1.id().get() - p2.id().get())
              .orElseThrow(
                  () ->
                      new IllegalStateException(
                          String.format(
                              "change %s can't load any patchset", getChangeId().toString())));
      return currentPatchset;
    }
    return getPatchSets().get(psId);
  }

  @Override
  protected void onLoad(LoadHandle handle) throws NoSuchChangeException, IOException {
    ObjectId rev = handle.id();
    if (rev == null) {
      if (shouldExist) {
        throw new NoSuchChangeException(getChangeId());
      }
      loadDefaults();
      return;
    }

    ChangeNotesCache.Value v =
        args.cache.get().get(getProjectName(), getChangeId(), rev, handle::walk);
    state = v.state();

    String stateServerId = state.serverId();
    /**
     * In earlier Gerrit versions serverId wasn't part of the change notes cache. That's why the
     * earlier cached entries don't have the serverId attribute. That's fine because in earlier
     * gerrit version serverId was already validated. Another approach to simplify the check would
     * be to bump the cache version, but that would invalidate all persistent cache entries, what we
     * rather try to avoid.
     */
    if (!Strings.isNullOrEmpty(stateServerId)
        && !args.serverId.equals(stateServerId)
        && !args.importedServerIds.contains(stateServerId)) {
      throw new InvalidServerIdException(args.serverId, stateServerId);
    }

    state.copyColumnsTo(change);
    revisionNoteMap = v.revisionNoteMap();
  }

  @Override
  protected void loadDefaults() {
    state = ChangeNotesState.empty(change);
  }

  @Override
  public Project.NameKey getProjectName() {
    return change.getProject();
  }

  @Nullable
  @Override
  protected ObjectId readRef(Repository repo) throws IOException {
    return refs != null ? refs.get(getRefName()).orElse(null) : super.readRef(repo);
  }
}
