// Copyright (C) 2009 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.Preconditions.checkNotNull;
import static com.google.gerrit.server.ApprovalsUtil.sortApprovals;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;
import static java.util.stream.Collectors.toSet;

import com.google.auto.value.AutoValue;
import com.google.common.base.MoreObjects;
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.ImmutableSortedSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.data.LabelTypes;
import com.google.gerrit.common.data.SubmitRecord;
import com.google.gerrit.common.data.SubmitTypeRecord;
import com.google.gerrit.extensions.client.DiffPreferencesInfo.Whitespace;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.ChangeMessage;
import com.google.gerrit.reviewdb.client.Comment;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.PatchSetApproval;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.reviewdb.client.RobotComment;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.ApprovalsUtil;
import com.google.gerrit.server.ChangeMessagesUtil;
import com.google.gerrit.server.CommentsUtil;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.PatchSetUtil;
import com.google.gerrit.server.ReviewerByEmailSet;
import com.google.gerrit.server.ReviewerSet;
import com.google.gerrit.server.ReviewerStatusUpdate;
import com.google.gerrit.server.StarredChangesUtil;
import com.google.gerrit.server.StarredChangesUtil.StarRef;
import com.google.gerrit.server.change.GetPureRevert;
import com.google.gerrit.server.change.MergeabilityCache;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.config.TrackingFooters;
import com.google.gerrit.server.diff.DiffSummary;
import com.google.gerrit.server.diff.DiffSummary.ChangedLines;
import com.google.gerrit.server.diff.DiffSummaryKey;
import com.google.gerrit.server.diff.PatchListCache;
import com.google.gerrit.server.diff.PatchListKey;
import com.google.gerrit.server.diff.PatchListNotAvailableException;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.MergeUtil;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.NotesMigration;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.project.SubmitRuleEvaluator;
import com.google.gerrit.server.project.SubmitRuleOptions;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.ResultSet;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Stream;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.FooterLine;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;

public class ChangeData {
  private static final int BATCH_SIZE = 50;

  public static List<Change> asChanges(List<ChangeData> changeDatas) throws OrmException {
    List<Change> result = new ArrayList<>(changeDatas.size());
    for (ChangeData cd : changeDatas) {
      result.add(cd.change());
    }
    return result;
  }

  public static Map<Change.Id, ChangeData> asMap(List<ChangeData> changes) {
    return changes.stream().collect(toMap(ChangeData::getId, cd -> cd));
  }

  public static void ensureChangeLoaded(Iterable<ChangeData> changes) throws OrmException {
    ChangeData first = Iterables.getFirst(changes, null);
    if (first == null) {
      return;
    } else if (first.notesMigration.readChanges()) {
      for (ChangeData cd : changes) {
        cd.change();
      }
      return;
    }

    Map<Change.Id, ChangeData> missing = new HashMap<>();
    for (ChangeData cd : changes) {
      if (cd.change == null) {
        missing.put(cd.getId(), cd);
      }
    }
    if (missing.isEmpty()) {
      return;
    }
    for (ChangeNotes notes : first.notesFactory.create(first.db, missing.keySet())) {
      missing.get(notes.getChangeId()).change = notes.getChange();
    }
  }

  public static void ensureAllPatchSetsLoaded(Iterable<ChangeData> changes) throws OrmException {
    ChangeData first = Iterables.getFirst(changes, null);
    if (first == null) {
      return;
    } else if (first.notesMigration.readChanges()) {
      for (ChangeData cd : changes) {
        cd.patchSets();
      }
      return;
    }

    List<ResultSet<PatchSet>> results = new ArrayList<>(BATCH_SIZE);
    for (List<ChangeData> batch : Iterables.partition(changes, BATCH_SIZE)) {
      results.clear();
      for (ChangeData cd : batch) {
        if (cd.patchSets == null) {
          results.add(cd.db.patchSets().byChange(cd.getId()));
        } else {
          results.add(null);
        }
      }
      for (int i = 0; i < batch.size(); i++) {
        ResultSet<PatchSet> result = results.get(i);
        if (result != null) {
          batch.get(i).patchSets = result.toList();
        }
      }
    }
  }

  public static void ensureCurrentPatchSetLoaded(Iterable<ChangeData> changes) throws OrmException {
    ChangeData first = Iterables.getFirst(changes, null);
    if (first == null) {
      return;
    } else if (first.notesMigration.readChanges()) {
      for (ChangeData cd : changes) {
        cd.currentPatchSet();
      }
      return;
    }

    Map<PatchSet.Id, ChangeData> missing = new HashMap<>();
    for (ChangeData cd : changes) {
      if (cd.currentPatchSet == null && cd.patchSets == null) {
        missing.put(cd.change().currentPatchSetId(), cd);
      }
    }
    if (missing.isEmpty()) {
      return;
    }
    for (PatchSet ps : first.db.patchSets().get(missing.keySet())) {
      missing.get(ps.getId()).currentPatchSet = ps;
    }
  }

  public static void ensureCurrentApprovalsLoaded(Iterable<ChangeData> changes)
      throws OrmException {
    ChangeData first = Iterables.getFirst(changes, null);
    if (first == null) {
      return;
    } else if (first.notesMigration.readChanges()) {
      for (ChangeData cd : changes) {
        cd.currentApprovals();
      }
      return;
    }

    List<ResultSet<PatchSetApproval>> results = new ArrayList<>(BATCH_SIZE);
    for (List<ChangeData> batch : Iterables.partition(changes, BATCH_SIZE)) {
      results.clear();
      for (ChangeData cd : batch) {
        if (cd.currentApprovals == null) {
          PatchSet.Id psId = cd.change().currentPatchSetId();
          results.add(cd.db.patchSetApprovals().byPatchSet(psId));
        } else {
          results.add(null);
        }
      }
      for (int i = 0; i < batch.size(); i++) {
        ResultSet<PatchSetApproval> result = results.get(i);
        if (result != null) {
          batch.get(i).currentApprovals = sortApprovals(result);
        }
      }
    }
  }

  public static void ensureMessagesLoaded(Iterable<ChangeData> changes) throws OrmException {
    ChangeData first = Iterables.getFirst(changes, null);
    if (first == null) {
      return;
    } else if (first.notesMigration.readChanges()) {
      for (ChangeData cd : changes) {
        cd.messages();
      }
      return;
    }

    List<ResultSet<ChangeMessage>> results = new ArrayList<>(BATCH_SIZE);
    for (List<ChangeData> batch : Iterables.partition(changes, BATCH_SIZE)) {
      results.clear();
      for (ChangeData cd : batch) {
        if (cd.messages == null) {
          PatchSet.Id psId = cd.change().currentPatchSetId();
          results.add(cd.db.changeMessages().byPatchSet(psId));
        } else {
          results.add(null);
        }
      }
      for (int i = 0; i < batch.size(); i++) {
        ResultSet<ChangeMessage> result = results.get(i);
        if (result != null) {
          batch.get(i).messages = result.toList();
        }
      }
    }
  }

  public static void ensureReviewedByLoadedForOpenChanges(Iterable<ChangeData> changes)
      throws OrmException {
    List<ChangeData> pending = new ArrayList<>();
    for (ChangeData cd : changes) {
      if (cd.reviewedBy == null && cd.change().getStatus().isOpen()) {
        pending.add(cd);
      }
    }

    if (!pending.isEmpty()) {
      ensureAllPatchSetsLoaded(pending);
      ensureMessagesLoaded(pending);
      for (ChangeData cd : pending) {
        cd.reviewedBy();
      }
    }
  }

  public static class Factory {
    private final AssistedFactory assistedFactory;

    @Inject
    Factory(AssistedFactory assistedFactory) {
      this.assistedFactory = assistedFactory;
    }

    public ChangeData create(ReviewDb db, Project.NameKey project, Change.Id id) {
      return assistedFactory.create(db, project, id, null, null);
    }

    public ChangeData create(ReviewDb db, Change change) {
      return assistedFactory.create(db, change.getProject(), change.getId(), change, null);
    }

    public ChangeData create(ReviewDb db, ChangeNotes notes) {
      return assistedFactory.create(
          db, notes.getChange().getProject(), notes.getChangeId(), notes.getChange(), notes);
    }
  }

  public interface AssistedFactory {
    ChangeData create(
        ReviewDb db,
        Project.NameKey project,
        Change.Id id,
        @Nullable Change change,
        @Nullable ChangeNotes notes);
  }

  /**
   * Create an instance for testing only.
   *
   * <p>Attempting to lazy load data will fail with NPEs. Callers may consider manually setting
   * fields that can be set.
   *
   * @param id change ID
   * @return instance for testing.
   */
  public static ChangeData createForTest(
      Project.NameKey project, Change.Id id, int currentPatchSetId) {
    ChangeData cd =
        new ChangeData(
            null, null, null, null, null, null, null, null, null, null, null, null, null, null,
            null, null, null, null, project, id, null, null);
    cd.currentPatchSet = new PatchSet(new PatchSet.Id(id, currentPatchSetId));
    return cd;
  }

  // Injected fields.
  private @Nullable final StarredChangesUtil starredChangesUtil;
  private final AllUsersName allUsersName;
  private final ApprovalsUtil approvalsUtil;
  private final ChangeMessagesUtil cmUtil;
  private final ChangeNotes.Factory notesFactory;
  private final CommentsUtil commentsUtil;
  private final GitRepositoryManager repoManager;
  private final IdentifiedUser.GenericFactory userFactory;
  private final MergeUtil.Factory mergeUtilFactory;
  private final MergeabilityCache mergeabilityCache;
  private final NotesMigration notesMigration;
  private final PatchListCache patchListCache;
  private final PatchSetUtil psUtil;
  private final ProjectCache projectCache;
  private final TrackingFooters trackingFooters;
  private final GetPureRevert pureRevert;
  private final SubmitRuleEvaluator.Factory submitRuleEvaluatorFactory;

  // Required assisted injected fields.
  private final ReviewDb db;
  private final Project.NameKey project;
  private final Change.Id legacyId;

  // Lazily populated fields, including optional assisted injected fields.

  private final Map<SubmitRuleOptions, List<SubmitRecord>> submitRecords =
      Maps.newLinkedHashMapWithExpectedSize(1);

  private boolean lazyLoad = true;
  private Change change;
  private ChangeNotes notes;
  private String commitMessage;
  private List<FooterLine> commitFooters;
  private PatchSet currentPatchSet;
  private Collection<PatchSet> patchSets;
  private ListMultimap<PatchSet.Id, PatchSetApproval> allApprovals;
  private List<PatchSetApproval> currentApprovals;
  private List<String> currentFiles;
  private Optional<DiffSummary> diffSummary;
  private Collection<Comment> publishedComments;
  private Collection<RobotComment> robotComments;
  private CurrentUser visibleTo;
  private List<ChangeMessage> messages;
  private Optional<ChangedLines> changedLines;
  private SubmitTypeRecord submitTypeRecord;
  private Boolean mergeable;
  private Set<String> hashtags;
  private Map<Account.Id, Ref> editsByUser;
  private Set<Account.Id> reviewedBy;
  private Map<Account.Id, Ref> draftsByUser;
  private ImmutableListMultimap<Account.Id, String> stars;
  private StarsOf starsOf;
  private ImmutableMap<Account.Id, StarRef> starRefs;
  private ReviewerSet reviewers;
  private ReviewerByEmailSet reviewersByEmail;
  private ReviewerSet pendingReviewers;
  private ReviewerByEmailSet pendingReviewersByEmail;
  private List<ReviewerStatusUpdate> reviewerUpdates;
  private PersonIdent author;
  private PersonIdent committer;
  private int parentCount;
  private Integer unresolvedCommentCount;
  private LabelTypes labelTypes;

  private ImmutableList<byte[]> refStates;
  private ImmutableList<byte[]> refStatePatterns;

  @Inject
  private ChangeData(
      @Nullable StarredChangesUtil starredChangesUtil,
      ApprovalsUtil approvalsUtil,
      AllUsersName allUsersName,
      ChangeMessagesUtil cmUtil,
      ChangeNotes.Factory notesFactory,
      CommentsUtil commentsUtil,
      GitRepositoryManager repoManager,
      IdentifiedUser.GenericFactory userFactory,
      MergeUtil.Factory mergeUtilFactory,
      MergeabilityCache mergeabilityCache,
      NotesMigration notesMigration,
      PatchListCache patchListCache,
      PatchSetUtil psUtil,
      ProjectCache projectCache,
      TrackingFooters trackingFooters,
      GetPureRevert pureRevert,
      SubmitRuleEvaluator.Factory submitRuleEvaluatorFactory,
      @Assisted ReviewDb db,
      @Assisted Project.NameKey project,
      @Assisted Change.Id id,
      @Assisted @Nullable Change change,
      @Assisted @Nullable ChangeNotes notes) {
    this.approvalsUtil = approvalsUtil;
    this.allUsersName = allUsersName;
    this.cmUtil = cmUtil;
    this.notesFactory = notesFactory;
    this.commentsUtil = commentsUtil;
    this.repoManager = repoManager;
    this.userFactory = userFactory;
    this.mergeUtilFactory = mergeUtilFactory;
    this.mergeabilityCache = mergeabilityCache;
    this.notesMigration = notesMigration;
    this.patchListCache = patchListCache;
    this.psUtil = psUtil;
    this.projectCache = projectCache;
    this.starredChangesUtil = starredChangesUtil;
    this.trackingFooters = trackingFooters;
    this.pureRevert = pureRevert;
    this.submitRuleEvaluatorFactory = submitRuleEvaluatorFactory;

    // May be null in tests when created via createForTest above, in which case lazy-loading will
    // intentionally fail with NPE. Still not marked @Nullable in the constructor, to force callers
    // using Guice to pass a non-null value.
    this.db = db;

    this.project = project;
    this.legacyId = id;

    this.change = change;
    this.notes = notes;
  }

  public ChangeData setLazyLoad(boolean load) {
    lazyLoad = load;
    return this;
  }

  public ReviewDb db() {
    return db;
  }

  public AllUsersName getAllUsersNameForIndexing() {
    return allUsersName;
  }

  public void setCurrentFilePaths(List<String> filePaths) throws OrmException {
    PatchSet ps = currentPatchSet();
    if (ps != null) {
      currentFiles = ImmutableList.copyOf(filePaths);
    }
  }

  public List<String> currentFilePaths() throws IOException, OrmException {
    if (currentFiles == null) {
      if (!lazyLoad) {
        return Collections.emptyList();
      }
      Optional<DiffSummary> p = getDiffSummary();
      currentFiles = p.map(DiffSummary::getPaths).orElse(Collections.emptyList());
    }
    return currentFiles;
  }

  private Optional<DiffSummary> getDiffSummary() throws OrmException, IOException {
    if (diffSummary == null) {
      if (!lazyLoad) {
        return Optional.empty();
      }

      Change c = change();
      PatchSet ps = currentPatchSet();
      if (c == null || ps == null || !loadCommitData()) {
        return Optional.empty();
      }

      ObjectId id = ObjectId.fromString(ps.getRevision().get());
      Whitespace ws = Whitespace.IGNORE_NONE;
      PatchListKey pk =
          parentCount > 1
              ? PatchListKey.againstParentNum(1, id, ws)
              : PatchListKey.againstDefaultBase(id, ws);
      DiffSummaryKey key = DiffSummaryKey.fromPatchListKey(pk);
      try {
        diffSummary = Optional.of(patchListCache.getDiffSummary(key, c.getProject()));
      } catch (PatchListNotAvailableException e) {
        diffSummary = Optional.empty();
      }
    }
    return diffSummary;
  }

  private Optional<ChangedLines> computeChangedLines() throws OrmException, IOException {
    Optional<DiffSummary> ds = getDiffSummary();
    if (ds.isPresent()) {
      return Optional.of(ds.get().getChangedLines());
    }
    return Optional.empty();
  }

  public Optional<ChangedLines> changedLines() throws OrmException, IOException {
    if (changedLines == null) {
      if (!lazyLoad) {
        return Optional.empty();
      }
      changedLines = computeChangedLines();
    }
    return changedLines;
  }

  public void setChangedLines(int insertions, int deletions) {
    changedLines = Optional.of(new ChangedLines(insertions, deletions));
  }

  public void setNoChangedLines() {
    changedLines = Optional.empty();
  }

  public Change.Id getId() {
    return legacyId;
  }

  public Project.NameKey project() {
    return project;
  }

  boolean fastIsVisibleTo(CurrentUser user) {
    return visibleTo == user;
  }

  void cacheVisibleTo(CurrentUser user) {
    visibleTo = user;
  }

  public Change change() throws OrmException {
    if (change == null && lazyLoad) {
      reloadChange();
    }
    return change;
  }

  public void setChange(Change c) {
    change = c;
  }

  public Change reloadChange() throws OrmException {
    try {
      notes = notesFactory.createChecked(db, project, legacyId);
    } catch (NoSuchChangeException e) {
      throw new OrmException("Unable to load change " + legacyId, e);
    }
    change = notes.getChange();
    setPatchSets(null);
    return change;
  }

  public LabelTypes getLabelTypes() throws OrmException {
    if (labelTypes == null) {
      ProjectState state;
      try {
        state = projectCache.checkedGet(project());
      } catch (IOException e) {
        throw new OrmException("project state not available", e);
      }
      labelTypes = state.getLabelTypes(change().getDest(), userFactory.create(change().getOwner()));
    }
    return labelTypes;
  }

  public ChangeNotes notes() throws OrmException {
    if (notes == null) {
      if (!lazyLoad) {
        throw new OrmException("ChangeNotes not available, lazyLoad = false");
      }
      notes = notesFactory.create(db, project(), legacyId);
    }
    return notes;
  }

  public PatchSet currentPatchSet() throws OrmException {
    if (currentPatchSet == null) {
      Change c = change();
      if (c == null) {
        return null;
      }
      for (PatchSet p : patchSets()) {
        if (p.getId().equals(c.currentPatchSetId())) {
          currentPatchSet = p;
          return p;
        }
      }
    }
    return currentPatchSet;
  }

  public List<PatchSetApproval> currentApprovals() throws OrmException {
    if (currentApprovals == null) {
      if (!lazyLoad) {
        return Collections.emptyList();
      }
      Change c = change();
      if (c == null) {
        currentApprovals = Collections.emptyList();
      } else {
        try {
          currentApprovals =
              ImmutableList.copyOf(
                  approvalsUtil.byPatchSet(
                      db,
                      notes(),
                      userFactory.create(c.getOwner()),
                      c.currentPatchSetId(),
                      null,
                      null));
        } catch (OrmException e) {
          if (e.getCause() instanceof NoSuchChangeException) {
            currentApprovals = Collections.emptyList();
          } else {
            throw e;
          }
        }
      }
    }
    return currentApprovals;
  }

  public void setCurrentApprovals(List<PatchSetApproval> approvals) {
    currentApprovals = approvals;
  }

  public String commitMessage() throws IOException, OrmException {
    if (commitMessage == null) {
      if (!loadCommitData()) {
        return null;
      }
    }
    return commitMessage;
  }

  public List<FooterLine> commitFooters() throws IOException, OrmException {
    if (commitFooters == null) {
      if (!loadCommitData()) {
        return null;
      }
    }
    return commitFooters;
  }

  public ListMultimap<String, String> trackingFooters() throws IOException, OrmException {
    return trackingFooters.extract(commitFooters());
  }

  public PersonIdent getAuthor() throws IOException, OrmException {
    if (author == null) {
      if (!loadCommitData()) {
        return null;
      }
    }
    return author;
  }

  public PersonIdent getCommitter() throws IOException, OrmException {
    if (committer == null) {
      if (!loadCommitData()) {
        return null;
      }
    }
    return committer;
  }

  private boolean loadCommitData()
      throws OrmException, RepositoryNotFoundException, IOException, MissingObjectException,
          IncorrectObjectTypeException {
    PatchSet ps = currentPatchSet();
    if (ps == null) {
      return false;
    }
    String sha1 = ps.getRevision().get();
    try (Repository repo = repoManager.openRepository(project());
        RevWalk walk = new RevWalk(repo)) {
      RevCommit c = walk.parseCommit(ObjectId.fromString(sha1));
      commitMessage = c.getFullMessage();
      commitFooters = c.getFooterLines();
      author = c.getAuthorIdent();
      committer = c.getCommitterIdent();
      parentCount = c.getParentCount();
    }
    return true;
  }

  /**
   * @return patches for the change, in patch set ID order.
   * @throws OrmException an error occurred reading the database.
   */
  public Collection<PatchSet> patchSets() throws OrmException {
    if (patchSets == null) {
      patchSets = psUtil.byChange(db, notes());
    }
    return patchSets;
  }

  public void setPatchSets(Collection<PatchSet> patchSets) {
    this.currentPatchSet = null;
    this.patchSets = patchSets;
  }

  /**
   * @return patch with the given ID, or null if it does not exist.
   * @throws OrmException an error occurred reading the database.
   */
  public PatchSet patchSet(PatchSet.Id psId) throws OrmException {
    if (currentPatchSet != null && currentPatchSet.getId().equals(psId)) {
      return currentPatchSet;
    }
    for (PatchSet ps : patchSets()) {
      if (ps.getId().equals(psId)) {
        return ps;
      }
    }
    return null;
  }

  /**
   * @return all patch set approvals for the change, keyed by ID, ordered by timestamp within each
   *     patch set.
   * @throws OrmException an error occurred reading the database.
   */
  public ListMultimap<PatchSet.Id, PatchSetApproval> approvals() throws OrmException {
    if (allApprovals == null) {
      if (!lazyLoad) {
        return ImmutableListMultimap.of();
      }
      allApprovals = approvalsUtil.byChange(db, notes());
    }
    return allApprovals;
  }

  /**
   * @return The submit ('SUBM') approval label
   * @throws OrmException an error occurred reading the database.
   */
  public Optional<PatchSetApproval> getSubmitApproval() throws OrmException {
    return currentApprovals().stream().filter(PatchSetApproval::isLegacySubmit).findFirst();
  }

  public ReviewerSet reviewers() throws OrmException {
    if (reviewers == null) {
      if (!lazyLoad) {
        return ReviewerSet.empty();
      }
      reviewers = approvalsUtil.getReviewers(notes(), approvals().values());
    }
    return reviewers;
  }

  public void setReviewers(ReviewerSet reviewers) {
    this.reviewers = reviewers;
  }

  public ReviewerSet getReviewers() {
    return reviewers;
  }

  public ReviewerByEmailSet reviewersByEmail() throws OrmException {
    if (reviewersByEmail == null) {
      if (!lazyLoad) {
        return ReviewerByEmailSet.empty();
      }
      reviewersByEmail = notes().getReviewersByEmail();
    }
    return reviewersByEmail;
  }

  public void setReviewersByEmail(ReviewerByEmailSet reviewersByEmail) {
    this.reviewersByEmail = reviewersByEmail;
  }

  public ReviewerByEmailSet getReviewersByEmail() {
    return reviewersByEmail;
  }

  public void setPendingReviewers(ReviewerSet pendingReviewers) {
    this.pendingReviewers = pendingReviewers;
  }

  public ReviewerSet getPendingReviewers() {
    return this.pendingReviewers;
  }

  public ReviewerSet pendingReviewers() throws OrmException {
    if (pendingReviewers == null) {
      if (!lazyLoad) {
        return ReviewerSet.empty();
      }
      pendingReviewers = notes().getPendingReviewers();
    }
    return pendingReviewers;
  }

  public void setPendingReviewersByEmail(ReviewerByEmailSet pendingReviewersByEmail) {
    this.pendingReviewersByEmail = pendingReviewersByEmail;
  }

  public ReviewerByEmailSet getPendingReviewersByEmail() {
    return pendingReviewersByEmail;
  }

  public ReviewerByEmailSet pendingReviewersByEmail() throws OrmException {
    if (pendingReviewersByEmail == null) {
      if (!lazyLoad) {
        return ReviewerByEmailSet.empty();
      }
      pendingReviewersByEmail = notes().getPendingReviewersByEmail();
    }
    return pendingReviewersByEmail;
  }

  public List<ReviewerStatusUpdate> reviewerUpdates() throws OrmException {
    if (reviewerUpdates == null) {
      if (!lazyLoad) {
        return Collections.emptyList();
      }
      reviewerUpdates = approvalsUtil.getReviewerUpdates(notes());
    }
    return reviewerUpdates;
  }

  public void setReviewerUpdates(List<ReviewerStatusUpdate> reviewerUpdates) {
    this.reviewerUpdates = reviewerUpdates;
  }

  public List<ReviewerStatusUpdate> getReviewerUpdates() {
    return reviewerUpdates;
  }

  public Collection<Comment> publishedComments() throws OrmException {
    if (publishedComments == null) {
      if (!lazyLoad) {
        return Collections.emptyList();
      }
      publishedComments = commentsUtil.publishedByChange(db, notes());
    }
    return publishedComments;
  }

  public Collection<RobotComment> robotComments() throws OrmException {
    if (robotComments == null) {
      if (!lazyLoad) {
        return Collections.emptyList();
      }
      robotComments = commentsUtil.robotCommentsByChange(notes());
    }
    return robotComments;
  }

  public Integer unresolvedCommentCount() throws OrmException {
    if (unresolvedCommentCount == null) {
      if (!lazyLoad) {
        return null;
      }

      List<Comment> comments =
          Stream.concat(publishedComments().stream(), robotComments().stream()).collect(toList());
      Set<String> nonLeafSet = comments.stream().map(c -> c.parentUuid).collect(toSet());

      Long count =
          comments.stream().filter(c -> (c.unresolved && !nonLeafSet.contains(c.key.uuid))).count();
      unresolvedCommentCount = count.intValue();
    }
    return unresolvedCommentCount;
  }

  public void setUnresolvedCommentCount(Integer count) {
    this.unresolvedCommentCount = count;
  }

  public List<ChangeMessage> messages() throws OrmException {
    if (messages == null) {
      if (!lazyLoad) {
        return Collections.emptyList();
      }
      messages = cmUtil.byChange(db, notes());
    }
    return messages;
  }

  public List<SubmitRecord> submitRecords(SubmitRuleOptions options) throws OrmException {
    List<SubmitRecord> records = submitRecords.get(options);
    if (records == null) {
      if (!lazyLoad) {
        return Collections.emptyList();
      }
      records =
          submitRuleEvaluatorFactory
              .create(userFactory.create(change().getOwner()), this)
              .setOptions(options)
              .evaluate();
      submitRecords.put(options, records);
    }
    return records;
  }

  @Nullable
  public List<SubmitRecord> getSubmitRecords(SubmitRuleOptions options) {
    return submitRecords.get(options);
  }

  public void setSubmitRecords(SubmitRuleOptions options, List<SubmitRecord> records) {
    submitRecords.put(options, records);
  }

  public SubmitTypeRecord submitTypeRecord() throws OrmException {
    if (submitTypeRecord == null) {
      submitTypeRecord =
          submitRuleEvaluatorFactory
              .create(userFactory.create(change().getOwner()), this)
              .getSubmitType();
    }
    return submitTypeRecord;
  }

  public void setMergeable(Boolean mergeable) {
    this.mergeable = mergeable;
  }

  public Boolean isMergeable() throws OrmException {
    if (mergeable == null) {
      Change c = change();
      if (c == null) {
        return null;
      }
      if (c.getStatus() == Change.Status.MERGED) {
        mergeable = true;
      } else if (c.getStatus() == Change.Status.ABANDONED) {
        return null;
      } else if (c.isWorkInProgress()) {
        return null;
      } else {
        if (!lazyLoad) {
          return null;
        }
        PatchSet ps = currentPatchSet();
        if (ps == null) {
          return null;
        }

        try (Repository repo = repoManager.openRepository(project())) {
          Ref ref = repo.getRefDatabase().exactRef(c.getDest().get());
          SubmitTypeRecord str = submitTypeRecord();
          if (!str.isOk()) {
            // If submit type rules are broken, it's definitely not mergeable.
            // No need to log, as SubmitRuleEvaluator already did it for us.
            return false;
          }
          String mergeStrategy =
              mergeUtilFactory.create(projectCache.get(project())).mergeStrategyName();
          mergeable =
              mergeabilityCache.get(
                  ObjectId.fromString(ps.getRevision().get()),
                  ref,
                  str.type,
                  mergeStrategy,
                  c.getDest(),
                  repo);
        } catch (IOException e) {
          throw new OrmException(e);
        }
      }
    }
    return mergeable;
  }

  public Set<Account.Id> editsByUser() throws OrmException {
    return editRefs().keySet();
  }

  public Map<Account.Id, Ref> editRefs() throws OrmException {
    if (editsByUser == null) {
      if (!lazyLoad) {
        return Collections.emptyMap();
      }
      Change c = change();
      if (c == null) {
        return Collections.emptyMap();
      }
      editsByUser = new HashMap<>();
      Change.Id id = checkNotNull(change.getId());
      try (Repository repo = repoManager.openRepository(project())) {
        for (Map.Entry<String, Ref> e :
            repo.getRefDatabase().getRefs(RefNames.REFS_USERS).entrySet()) {
          if (id.equals(Change.Id.fromEditRefPart(e.getKey()))) {
            editsByUser.put(Account.Id.fromRefPart(e.getKey()), e.getValue());
          }
        }
      } catch (IOException e) {
        throw new OrmException(e);
      }
    }
    return editsByUser;
  }

  public Set<Account.Id> draftsByUser() throws OrmException {
    return draftRefs().keySet();
  }

  public Map<Account.Id, Ref> draftRefs() throws OrmException {
    if (draftsByUser == null) {
      if (!lazyLoad) {
        return Collections.emptyMap();
      }
      Change c = change();
      if (c == null) {
        return Collections.emptyMap();
      }

      draftsByUser = new HashMap<>();
      if (notesMigration.readChanges()) {
        for (Ref ref : commentsUtil.getDraftRefs(notes.getChangeId())) {
          Account.Id account = Account.Id.fromRefSuffix(ref.getName());
          if (account != null
              // Double-check that any drafts exist for this user after
              // filtering out zombies. If some but not all drafts in the ref
              // were zombies, the returned Ref still includes those zombies;
              // this is suboptimal, but is ok for the purposes of
              // draftsByUser(), and easier than trying to rebuild the change at
              // this point.
              && !notes().getDraftComments(account, ref).isEmpty()) {
            draftsByUser.put(account, ref);
          }
        }
      } else {
        for (Comment sc : commentsUtil.draftByChange(db, notes())) {
          draftsByUser.put(sc.author.getId(), null);
        }
      }
    }
    return draftsByUser;
  }

  public boolean isReviewedBy(Account.Id accountId) throws OrmException {
    Collection<String> stars = stars(accountId);

    if (stars.contains(
        StarredChangesUtil.REVIEWED_LABEL + "/" + currentPatchSet().getPatchSetId())) {
      return true;
    }

    if (stars.contains(
        StarredChangesUtil.UNREVIEWED_LABEL + "/" + currentPatchSet().getPatchSetId())) {
      return false;
    }

    return reviewedBy().contains(accountId);
  }

  public Set<Account.Id> reviewedBy() throws OrmException {
    if (reviewedBy == null) {
      if (!lazyLoad) {
        return Collections.emptySet();
      }
      Change c = change();
      if (c == null) {
        return Collections.emptySet();
      }
      List<ReviewedByEvent> events = new ArrayList<>();
      for (ChangeMessage msg : messages()) {
        if (msg.getAuthor() != null) {
          events.add(ReviewedByEvent.create(msg));
        }
      }
      events = Lists.reverse(events);
      reviewedBy = new LinkedHashSet<>();
      Account.Id owner = c.getOwner();
      for (ReviewedByEvent event : events) {
        if (owner.equals(event.author())) {
          break;
        }
        reviewedBy.add(event.author());
      }
    }
    return reviewedBy;
  }

  public void setReviewedBy(Set<Account.Id> reviewedBy) {
    this.reviewedBy = reviewedBy;
  }

  public Set<String> hashtags() throws OrmException {
    if (hashtags == null) {
      if (!lazyLoad) {
        return Collections.emptySet();
      }
      hashtags = notes().getHashtags();
    }
    return hashtags;
  }

  public void setHashtags(Set<String> hashtags) {
    this.hashtags = hashtags;
  }

  public ImmutableListMultimap<Account.Id, String> stars() throws OrmException {
    if (stars == null) {
      if (!lazyLoad) {
        return ImmutableListMultimap.of();
      }
      ImmutableListMultimap.Builder<Account.Id, String> b = ImmutableListMultimap.builder();
      for (Map.Entry<Account.Id, StarRef> e : starRefs().entrySet()) {
        b.putAll(e.getKey(), e.getValue().labels());
      }
      return b.build();
    }
    return stars;
  }

  public void setStars(ListMultimap<Account.Id, String> stars) {
    this.stars = ImmutableListMultimap.copyOf(stars);
  }

  public ImmutableMap<Account.Id, StarRef> starRefs() throws OrmException {
    if (starRefs == null) {
      if (!lazyLoad) {
        return ImmutableMap.of();
      }
      starRefs = checkNotNull(starredChangesUtil).byChange(legacyId);
    }
    return starRefs;
  }

  public Set<String> stars(Account.Id accountId) throws OrmException {
    if (starsOf != null) {
      if (!starsOf.accountId().equals(accountId)) {
        starsOf = null;
      }
    }
    if (starsOf == null) {
      if (stars != null) {
        starsOf = StarsOf.create(accountId, stars.get(accountId));
      } else {
        if (!lazyLoad) {
          return ImmutableSet.of();
        }
        starsOf = StarsOf.create(accountId, starredChangesUtil.getLabels(accountId, legacyId));
      }
    }
    return starsOf.stars();
  }

  /**
   * @return {@code null} if {@code revertOf} is {@code null}; true if the change is a pure revert;
   *     false otherwise.
   */
  @Nullable
  public Boolean isPureRevert() throws OrmException {
    if (change().getRevertOf() == null) {
      return null;
    }
    try {
      return pureRevert.getPureRevert(notes()).isPureRevert;
    } catch (IOException | BadRequestException | ResourceConflictException e) {
      throw new OrmException("could not compute pure revert", e);
    }
  }

  @Override
  public String toString() {
    MoreObjects.ToStringHelper h = MoreObjects.toStringHelper(this);
    if (change != null) {
      h.addValue(change);
    } else {
      h.addValue(legacyId);
    }
    return h.toString();
  }

  public ImmutableList<byte[]> getRefStates() {
    return refStates;
  }

  public void setRefStates(Iterable<byte[]> refStates) {
    this.refStates = ImmutableList.copyOf(refStates);
  }

  public ImmutableList<byte[]> getRefStatePatterns() {
    return refStatePatterns;
  }

  public void setRefStatePatterns(Iterable<byte[]> refStatePatterns) {
    this.refStatePatterns = ImmutableList.copyOf(refStatePatterns);
  }

  @AutoValue
  abstract static class ReviewedByEvent {
    private static ReviewedByEvent create(ChangeMessage msg) {
      return new AutoValue_ChangeData_ReviewedByEvent(msg.getAuthor(), msg.getWrittenOn());
    }

    public abstract Account.Id author();

    public abstract Timestamp ts();
  }

  @AutoValue
  abstract static class StarsOf {
    private static StarsOf create(Account.Id accountId, Iterable<String> stars) {
      return new AutoValue_ChangeData_StarsOf(accountId, ImmutableSortedSet.copyOf(stars));
    }

    public abstract Account.Id accountId();

    public abstract ImmutableSortedSet<String> stars();
  }
}
