// Copyright (C) 2012 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.change;

import static com.google.common.collect.ImmutableMap.toImmutableMap;
import static com.google.gerrit.extensions.client.ListChangesOption.ALL_COMMITS;
import static com.google.gerrit.extensions.client.ListChangesOption.ALL_REVISIONS;
import static com.google.gerrit.extensions.client.ListChangesOption.CHANGE_ACTIONS;
import static com.google.gerrit.extensions.client.ListChangesOption.CHECK;
import static com.google.gerrit.extensions.client.ListChangesOption.COMMIT_FOOTERS;
import static com.google.gerrit.extensions.client.ListChangesOption.CURRENT_ACTIONS;
import static com.google.gerrit.extensions.client.ListChangesOption.CURRENT_COMMIT;
import static com.google.gerrit.extensions.client.ListChangesOption.CURRENT_REVISION;
import static com.google.gerrit.extensions.client.ListChangesOption.CUSTOM_KEYED_VALUES;
import static com.google.gerrit.extensions.client.ListChangesOption.DETAILED_ACCOUNTS;
import static com.google.gerrit.extensions.client.ListChangesOption.DETAILED_LABELS;
import static com.google.gerrit.extensions.client.ListChangesOption.LABELS;
import static com.google.gerrit.extensions.client.ListChangesOption.MESSAGES;
import static com.google.gerrit.extensions.client.ListChangesOption.REVIEWED;
import static com.google.gerrit.extensions.client.ListChangesOption.REVIEWER_UPDATES;
import static com.google.gerrit.extensions.client.ListChangesOption.SKIP_DIFFSTAT;
import static com.google.gerrit.extensions.client.ListChangesOption.STAR;
import static com.google.gerrit.extensions.client.ListChangesOption.SUBMITTABLE;
import static com.google.gerrit.extensions.client.ListChangesOption.SUBMIT_REQUIREMENTS;
import static com.google.gerrit.extensions.client.ListChangesOption.TRACKING_IDS;
import static com.google.gerrit.server.ChangeMessagesUtil.createChangeMessageInfo;
import static com.google.gerrit.server.util.AttentionSetUtil.additionsOnly;
import static com.google.gerrit.server.util.AttentionSetUtil.removalsOnly;
import static java.util.stream.Collectors.toList;

import com.google.common.base.Joiner;
import com.google.common.base.MoreObjects;
import com.google.common.base.Throwables;
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.ListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.flogger.FluentLogger;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Address;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.ChangeMessage;
import com.google.gerrit.entities.LegacySubmitRequirement;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.PatchSetApproval;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.SubmitRecord;
import com.google.gerrit.entities.SubmitRecord.Status;
import com.google.gerrit.entities.SubmitRequirementResult;
import com.google.gerrit.entities.SubmitTypeRecord;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.extensions.api.changes.FixInput;
import com.google.gerrit.extensions.client.ListChangesOption;
import com.google.gerrit.extensions.client.ReviewerState;
import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.common.ApprovalInfo;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.ChangeMessageInfo;
import com.google.gerrit.extensions.common.LabelInfo;
import com.google.gerrit.extensions.common.LegacySubmitRequirementInfo;
import com.google.gerrit.extensions.common.PluginDefinedInfo;
import com.google.gerrit.extensions.common.ProblemInfo;
import com.google.gerrit.extensions.common.ReviewerUpdateInfo;
import com.google.gerrit.extensions.common.RevisionInfo;
import com.google.gerrit.extensions.common.SubmitRecordInfo;
import com.google.gerrit.extensions.common.SubmitRequirementResultInfo;
import com.google.gerrit.extensions.common.TrackingIdInfo;
import com.google.gerrit.extensions.restapi.Url;
import com.google.gerrit.index.query.QueryResult;
import com.google.gerrit.metrics.Description;
import com.google.gerrit.metrics.Description.Units;
import com.google.gerrit.metrics.MetricMaker;
import com.google.gerrit.metrics.Timer0;
import com.google.gerrit.server.ChangeMessagesUtil;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.GpgException;
import com.google.gerrit.server.ReviewerByEmailSet;
import com.google.gerrit.server.ReviewerSet;
import com.google.gerrit.server.ReviewerStatusUpdate;
import com.google.gerrit.server.StarredChangesReader;
import com.google.gerrit.server.account.AccountInfoComparator;
import com.google.gerrit.server.account.AccountLoader;
import com.google.gerrit.server.cancellation.RequestCancelledException;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.TrackingFooters;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.index.change.ChangeField;
import com.google.gerrit.server.logging.Metadata;
import com.google.gerrit.server.logging.TraceContext;
import com.google.gerrit.server.logging.TraceContext.TraceTimer;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.ReviewerStateInternal;
import com.google.gerrit.server.patch.PatchListNotAvailableException;
import com.google.gerrit.server.permissions.ChangePermission;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.project.RemoveReviewerControl;
import com.google.gerrit.server.project.SubmitRuleOptions;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.ChangeData.ChangedLines;
import com.google.gerrit.server.util.AttentionSetUtil;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import com.google.inject.assistedinject.Assisted;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;

/**
 * Produces {@link ChangeInfo} (which is serialized to JSON afterwards) from {@link ChangeData}.
 *
 * <p>This is intended to be used on request scope, but may be used for converting multiple {@link
 * ChangeData} objects from different sources.
 */
public class ChangeJson {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  public static final SubmitRuleOptions SUBMIT_RULE_OPTIONS_LENIENT =
      ChangeField.SUBMIT_RULE_OPTIONS_LENIENT.toBuilder().build();

  public static final SubmitRuleOptions SUBMIT_RULE_OPTIONS_STRICT =
      ChangeField.SUBMIT_RULE_OPTIONS_STRICT.toBuilder().build();

  public static final ImmutableSet<ListChangesOption> REQUIRE_LAZY_LOAD =
      ImmutableSet.of(
          ALL_COMMITS,
          ALL_REVISIONS,
          CHANGE_ACTIONS,
          CHECK,
          COMMIT_FOOTERS,
          CURRENT_ACTIONS,
          CURRENT_COMMIT,
          MESSAGES);

  @Singleton
  public static class Factory {
    private final AssistedFactory factory;

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

    public ChangeJson noOptions() {
      return create(ImmutableSet.of());
    }

    public ChangeJson create(Iterable<ListChangesOption> options) {
      return factory.create(options, Optional.empty());
    }

    public ChangeJson create(
        Iterable<ListChangesOption> options, PluginDefinedInfosFactory pluginDefinedInfosFactory) {
      return factory.create(options, Optional.of(pluginDefinedInfosFactory));
    }

    public ChangeJson create(ListChangesOption first, ListChangesOption... rest) {
      return create(Sets.immutableEnumSet(first, rest));
    }
  }

  public interface AssistedFactory {
    ChangeJson create(
        Iterable<ListChangesOption> options,
        Optional<PluginDefinedInfosFactory> pluginDefinedInfosFactory);
  }

  @Singleton
  private static class Metrics {
    private final Timer0 toChangeInfoLatency;
    private final Timer0 toChangeInfosLatency;
    private final Timer0 formatQueryResultsLatency;

    @Inject
    Metrics(MetricMaker metricMaker) {
      toChangeInfoLatency =
          metricMaker.newTimer(
              "http/server/rest_api/change_json/to_change_info_latency",
              new Description("Latency for toChangeInfo invocations in ChangeJson")
                  .setCumulative()
                  .setUnit(Units.MILLISECONDS));
      toChangeInfosLatency =
          metricMaker.newTimer(
              "http/server/rest_api/change_json/to_change_infos_latency",
              new Description("Latency for toChangeInfos invocations in ChangeJson")
                  .setCumulative()
                  .setUnit(Units.MILLISECONDS));
      formatQueryResultsLatency =
          metricMaker.newTimer(
              "http/server/rest_api/change_json/format_query_results_latency",
              new Description("Latency for formatQueryResults invocations in ChangeJson")
                  .setCumulative()
                  .setUnit(Units.MILLISECONDS));
    }
  }

  private final GitRepositoryManager repoManager;
  private final AllUsersName allUsers;
  private final Provider<CurrentUser> userProvider;
  private final PermissionBackend permissionBackend;
  private final ChangeData.Factory changeDataFactory;
  private final AccountLoader.Factory accountLoaderFactory;
  private final ImmutableSet<ListChangesOption> options;
  private final ChangeMessagesUtil cmUtil;
  private final StarredChangesReader starredChangesreader;
  private final Provider<ConsistencyChecker> checkerProvider;
  private final ActionJson actionJson;
  private final ChangeNotes.Factory notesFactory;
  private final LabelsJson labelsJson;
  private final RemoveReviewerControl removeReviewerControl;
  private final TrackingFooters trackingFooters;
  private final Metrics metrics;
  private final RevisionJson revisionJson;
  private final Optional<PluginDefinedInfosFactory> pluginDefinedInfosFactory;
  private final boolean includeMergeable;
  private final boolean lazyLoad;
  private final boolean cacheQueryResultsByChangeNum;

  private AccountLoader accountLoader;
  private FixInput fix;

  @Inject
  ChangeJson(
      GitRepositoryManager repoManager,
      AllUsersName allUsers,
      Provider<CurrentUser> user,
      PermissionBackend permissionBackend,
      ChangeData.Factory cdf,
      AccountLoader.Factory ailf,
      ChangeMessagesUtil cmUtil,
      StarredChangesReader starredChangesreader,
      Provider<ConsistencyChecker> checkerProvider,
      ActionJson actionJson,
      ChangeNotes.Factory notesFactory,
      LabelsJson labelsJson,
      RemoveReviewerControl removeReviewerControl,
      TrackingFooters trackingFooters,
      Metrics metrics,
      RevisionJson.Factory revisionJsonFactory,
      @GerritServerConfig Config cfg,
      @Assisted Iterable<ListChangesOption> options,
      @Assisted Optional<PluginDefinedInfosFactory> pluginDefinedInfosFactory) {
    this.repoManager = repoManager;
    this.allUsers = allUsers;
    this.userProvider = user;
    this.changeDataFactory = cdf;
    this.permissionBackend = permissionBackend;
    this.accountLoaderFactory = ailf;
    this.cmUtil = cmUtil;
    this.starredChangesreader = starredChangesreader;
    this.checkerProvider = checkerProvider;
    this.actionJson = actionJson;
    this.notesFactory = notesFactory;
    this.labelsJson = labelsJson;
    this.removeReviewerControl = removeReviewerControl;
    this.trackingFooters = trackingFooters;
    this.metrics = metrics;
    this.revisionJson = revisionJsonFactory.create(options);
    this.options = Sets.immutableEnumSet(options);
    this.includeMergeable = MergeabilityComputationBehavior.fromConfig(cfg).includeInApi();
    this.lazyLoad = containsAnyOf(this.options, REQUIRE_LAZY_LOAD);
    this.pluginDefinedInfosFactory = pluginDefinedInfosFactory;
    this.cacheQueryResultsByChangeNum =
        cfg.getBoolean("index", "cacheQueryResultsByChangeNum", true);

    logger.atFine().log("options = %s", options);
  }

  @CanIgnoreReturnValue
  public ChangeJson fix(FixInput fix) {
    this.fix = fix;
    return this;
  }

  public ChangeInfo format(ChangeResource rsrc) {
    return format(changeDataFactory.create(rsrc.getNotes()));
  }

  public ChangeInfo format(Change change) {
    return format(changeDataFactory.create(change));
  }

  public ChangeInfo format(Change change, @Nullable ObjectId metaRevId) {
    ChangeNotes notes = notesFactory.createChecked(change.getProject(), change.getId(), metaRevId);
    return format(changeDataFactory.create(notes));
  }

  public ChangeInfo format(ChangeData cd) {
    return format(cd, Optional.empty(), true, getPluginInfos(cd));
  }

  public ChangeInfo format(RevisionResource rsrc) {
    ChangeData cd = changeDataFactory.create(rsrc.getNotes());
    return format(cd, Optional.of(rsrc.getPatchSet().id()), true, getPluginInfos(cd));
  }

  public List<List<ChangeInfo>> format(List<QueryResult<ChangeData>> in)
      throws PermissionBackendException {
    try (Timer0.Context ignored = metrics.formatQueryResultsLatency.start()) {
      accountLoader = accountLoaderFactory.create(has(DETAILED_ACCOUNTS));
      List<List<ChangeInfo>> res = new ArrayList<>(in.size());
      Map<Change.Id, ChangeInfo> cache = Maps.newHashMapWithExpectedSize(in.size());
      ImmutableListMultimap<Change.Id, PluginDefinedInfo> pluginInfosByChange =
          getPluginInfos(in.stream().flatMap(e -> e.entities().stream()).collect(toList()));
      for (QueryResult<ChangeData> r : in) {
        List<ChangeInfo> infos = toChangeInfos(r.entities(), cache, pluginInfosByChange);
        if (!infos.isEmpty() && r.more()) {
          infos.get(infos.size() - 1)._moreChanges = true;
        }
        res.add(infos);
      }
      accountLoader.fill();
      return res;
    }
  }

  public List<ChangeInfo> format(Collection<ChangeData> in) throws PermissionBackendException {
    accountLoader = accountLoaderFactory.create(has(DETAILED_ACCOUNTS));
    ensureLoaded(in);
    List<ChangeInfo> out = new ArrayList<>(in.size());
    ImmutableListMultimap<Change.Id, PluginDefinedInfo> pluginInfosByChange = getPluginInfos(in);
    for (ChangeData cd : in) {
      out.add(format(cd, Optional.empty(), false, pluginInfosByChange.get(cd.getId())));
    }
    accountLoader.fill();
    return out;
  }

  public ChangeInfo format(Project.NameKey project, Change.Id id) {
    return format(project, id, null);
  }

  public ChangeInfo format(Project.NameKey project, Change.Id id, @Nullable ObjectId metaRevId) {
    ChangeNotes notes;
    try {
      notes = notesFactory.createChecked(project, id, metaRevId);
    } catch (StorageException e) {
      if (!has(CHECK)) {
        throw e;
      }
      return checkOnly(changeDataFactory.create(project, id));
    }
    ChangeData cd = changeDataFactory.create(notes);
    return format(cd, Optional.empty(), true, getPluginInfos(cd));
  }

  private static List<LegacySubmitRequirementInfo> requirementsFor(ChangeData cd) {
    try (TraceTimer timer =
        TraceContext.newTimer(
            "Get requirements", Metadata.builder().changeId(cd.change().getId().get()).build())) {
      List<LegacySubmitRequirementInfo> reqInfos = new ArrayList<>();
      for (SubmitRecord submitRecord : cd.submitRecords(SUBMIT_RULE_OPTIONS_STRICT)) {
        if (submitRecord.requirements == null) {
          continue;
        }
        for (LegacySubmitRequirement requirement : submitRecord.requirements) {
          reqInfos.add(requirementToInfo(requirement, submitRecord.status));
        }
      }
      return reqInfos;
    }
  }

  private List<SubmitRecordInfo> submitRecordsFor(ChangeData cd) {
    try (TraceTimer timer =
        TraceContext.newTimer(
            "Get submit records", Metadata.builder().changeId(cd.change().getId().get()).build())) {
      List<SubmitRecordInfo> submitRecordInfos = new ArrayList<>();
      for (SubmitRecord record : cd.submitRecords(SUBMIT_RULE_OPTIONS_STRICT)) {
        submitRecordInfos.add(submitRecordToInfo(record));
      }
      return submitRecordInfos;
    }
  }

  private List<SubmitRequirementResultInfo> submitRequirementsFor(ChangeData cd) {
    try (TraceTimer timer =
        TraceContext.newTimer(
            "Get submit requirements",
            Metadata.builder().changeId(cd.change().getId().get()).build())) {
      List<SubmitRequirementResultInfo> reqInfos = new ArrayList<>();
      cd.submitRequirementsIncludingLegacy().entrySet().stream()
          .filter(entry -> !entry.getValue().isHidden())
          .forEach(
              entry ->
                  reqInfos.add(SubmitRequirementsJson.toInfo(entry.getKey(), entry.getValue())));
      return reqInfos;
    }
  }

  private static LegacySubmitRequirementInfo requirementToInfo(
      LegacySubmitRequirement req, Status status) {
    return new LegacySubmitRequirementInfo(status.name(), req.fallbackText(), req.type());
  }

  private SubmitRecordInfo submitRecordToInfo(SubmitRecord record) {
    SubmitRecordInfo info = new SubmitRecordInfo();
    if (record.status != null) {
      info.status = SubmitRecordInfo.Status.valueOf(record.status.name());
    }
    info.ruleName = record.ruleName;
    info.errorMessage = record.errorMessage;
    if (record.labels != null) {
      info.labels = new ArrayList<>();
      for (SubmitRecord.Label label : record.labels) {
        SubmitRecordInfo.Label labelInfo = new SubmitRecordInfo.Label();
        labelInfo.label = label.label;
        if (label.status != null) {
          labelInfo.status = SubmitRecordInfo.Label.Status.valueOf(label.status.name());
        }
        labelInfo.appliedBy = accountLoader.get(label.appliedBy);
        info.labels.add(labelInfo);
      }
    }
    if (record.requirements != null) {
      info.requirements = new ArrayList<>();
      for (LegacySubmitRequirement requirement : record.requirements) {
        info.requirements.add(requirementToInfo(requirement, record.status));
      }
    }
    return info;
  }

  private static void finish(ChangeInfo info) {
    info.tripletId =
        Joiner.on('~')
            .join(Url.encode(info.project), Url.encode(info.branch), Url.encode(info.changeId));
    info.id =
        Joiner.on('~').join(Url.encode(info.project), Url.encode(String.valueOf(info._number)));
  }

  private static boolean containsAnyOf(
      ImmutableSet<ListChangesOption> set, ImmutableSet<ListChangesOption> toFind) {
    return !Sets.intersection(toFind, set).isEmpty();
  }

  private ChangeInfo format(
      ChangeData cd,
      Optional<PatchSet.Id> limitToPsId,
      boolean fillAccountLoader,
      List<PluginDefinedInfo> pluginInfosForChange) {
    try {
      if (fillAccountLoader) {
        accountLoader = accountLoaderFactory.create(has(DETAILED_ACCOUNTS));
        ChangeInfo res = toChangeInfo(cd, limitToPsId, pluginInfosForChange);
        accountLoader.fill();
        return res;
      }
      return toChangeInfo(cd, limitToPsId, pluginInfosForChange);
    } catch (PatchListNotAvailableException
        | GpgException
        | IOException
        | PermissionBackendException
        | RuntimeException e) {
      if (!has(CHECK)) {
        Throwables.throwIfInstanceOf(e, StorageException.class);
        throw new StorageException(e);
      }
      return checkOnly(cd);
    }
  }

  private void ensureLoaded(Collection<ChangeData> all) {
    if (lazyLoad) {
      try (TraceTimer timer =
          TraceContext.newTimer(
              "Load change data for lazyLoad options",
              Metadata.builder().resourceCount(all.size()).build())) {
        for (ChangeData cd : all) {
          // Mark all ChangeDatas as coming from the index, but allow backfilling data from NoteDb
          cd.setStorageConstraint(ChangeData.StorageConstraint.INDEX_PRIMARY_NOTEDB_SECONDARY);
        }
        ChangeData.ensureChangeLoaded(all);
        if (has(ALL_REVISIONS)) {
          ChangeData.ensureAllPatchSetsLoaded(all);
        } else if (has(CURRENT_REVISION) || has(MESSAGES)) {
          ChangeData.ensureCurrentPatchSetLoaded(all);
        }
        if (has(REVIEWED) && userProvider.get().isIdentifiedUser()) {
          ChangeData.ensureReviewedByLoadedForOpenChanges(all);
        }
        if (has(STAR) && userProvider.get().isIdentifiedUser()) {
          ChangeData.ensureChangeServerId(all);
        }
        ChangeData.ensureCurrentApprovalsLoaded(all);
      }
    } else {
      for (ChangeData cd : all) {
        // Mark all ChangeDatas as coming from the index. Disallow using NoteDb
        cd.setStorageConstraint(ChangeData.StorageConstraint.INDEX_ONLY);
      }
    }
  }

  private boolean has(ListChangesOption option) {
    return options.contains(option);
  }

  private List<ChangeInfo> toChangeInfos(
      List<ChangeData> changes,
      Map<Change.Id, ChangeInfo> cache,
      ImmutableListMultimap<Change.Id, PluginDefinedInfo> pluginInfosByChange) {
    try (Timer0.Context ignored = metrics.toChangeInfosLatency.start()) {
      List<ChangeInfo> changeInfos = new ArrayList<>(changes.size());
      for (int i = 0; i < changes.size(); i++) {
        // We can only cache and re-use an entity if it's not the last in the list. The last entity
        // may later get _moreChanges set. If it was cached or re-used, that setting would propagate
        // to the original entity yielding wrong results.
        // This problem has two sides where 'last in the list' has to be respected:
        // (1) Caching
        // (2) Reusing
        boolean isCacheable = cacheQueryResultsByChangeNum && (i != changes.size() - 1);
        ChangeData cd = changes.get(i);
        if (cd.hasFailedParsingFromIndex()) {
          Optional<ChangeInfo> faultyChangeInfo = createFaultyChangeInfo(cd);
          if (faultyChangeInfo.isPresent()) {
            changeInfos.add(faultyChangeInfo.get());
          }
          continue;
        }
        Change.Id cdUniqueId = cd.virtualId();
        ChangeInfo info = cache.get(cdUniqueId);
        if (info != null && isCacheable) {
          changeInfos.add(info);
          continue;
        }

        // Compute and cache if possible
        try {
          ensureLoaded(Collections.singleton(cd));
          info = format(cd, Optional.empty(), false, pluginInfosByChange.get(cd.getId()));
          changeInfos.add(info);
          if (isCacheable) {
            cache.put(cdUniqueId, info);
          }
        } catch (RuntimeException e) {
          Optional<RequestCancelledException> requestCancelledException =
              RequestCancelledException.getFromCausalChain(e);
          if (requestCancelledException.isPresent()) {
            throw e;
          }
          logger.atWarning().withCause(e).log(
              "Omitting corrupt change %s from results", cd.getId());
        }
      }
      if (has(STAR) && userProvider.get().isIdentifiedUser()) {
        populateStarField(changeInfos);
      }
      return changeInfos;
    }
  }

  private ChangeInfo checkOnly(ChangeData cd) {
    ChangeNotes notes;
    try {
      notes = cd.notes();
    } catch (StorageException e) {
      String msg = "Error loading change";
      logger.atWarning().withCause(e).log(msg + " %s", cd.getId());
      ChangeInfo info = new ChangeInfo();
      info._number = cd.getId().get();
      ProblemInfo p = new ProblemInfo();
      p.message = msg;
      info.problems = Lists.newArrayList(p);
      return info;
    }

    ConsistencyChecker.Result result = checkerProvider.get().check(notes, fix);
    ChangeInfo info = new ChangeInfo();
    Change c = result.change();
    if (c != null) {
      info.project = c.getProject().get();
      info.branch = c.getDest().shortName();
      info.topic = c.getTopic();
      info.changeId = c.getKey().get();
      info.subject = c.getSubject();
      info.status = c.getStatus().asChangeStatus();
      info.owner = new AccountInfo(c.getOwner().get());
      info.setCreated(c.getCreatedOn());
      info.setUpdated(c.getLastUpdatedOn());
      info._number = c.getId().get();
      info.problems = result.problems();
      info.isPrivate = c.isPrivate() ? true : null;
      info.workInProgress = c.isWorkInProgress() ? true : null;
      info.hasReviewStarted = c.hasReviewStarted();
      finish(info);
    } else {
      info._number = result.id().get();
      info.problems = result.problems();
    }
    return info;
  }

  private ChangeInfo toChangeInfo(
      ChangeData cd,
      Optional<PatchSet.Id> limitToPsId,
      List<PluginDefinedInfo> pluginInfosForChange)
      throws PatchListNotAvailableException, GpgException, PermissionBackendException, IOException {
    try (Timer0.Context ignored = metrics.toChangeInfoLatency.start()) {
      return toChangeInfoImpl(cd, limitToPsId, pluginInfosForChange);
    }
  }

  private ChangeInfo toChangeInfoImpl(
      ChangeData cd, Optional<PatchSet.Id> limitToPsId, List<PluginDefinedInfo> pluginInfos)
      throws PatchListNotAvailableException, GpgException, PermissionBackendException, IOException {
    ChangeInfo out = new ChangeInfo();
    CurrentUser user = userProvider.get();

    if (has(CHECK)) {
      out.problems = checkerProvider.get().check(cd.notes(), fix).problems();
      // If any problems were fixed, the ChangeData needs to be reloaded.
      if (out.problems.stream().anyMatch(p -> p.status == ProblemInfo.Status.FIXED)) {
        try (TraceTimer timer =
            TraceContext.newTimer(
                "Reload change data after fixing a problem",
                Metadata.builder().changeId(cd.change().getChangeId()).build())) {
          cd = changeDataFactory.create(cd.project(), cd.getId());
        }
      }
    }

    Change in = cd.change();
    out.project = in.getProject().get();
    out.branch = in.getDest().shortName();
    out.currentRevisionNumber = in.currentPatchSetId().get();
    out.topic = in.getTopic();
    if (!cd.attentionSet().isEmpty()) {
      out.removedFromAttentionSet =
          removalsOnly(cd.attentionSet()).stream()
              .collect(
                  toImmutableMap(
                      a -> a.account().get(),
                      a -> AttentionSetUtil.createAttentionSetInfo(a, accountLoader)));
      out.attentionSet =
          // This filtering should match GetAttentionSet.
          additionsOnly(cd.attentionSet()).stream()
              .collect(
                  toImmutableMap(
                      a -> a.account().get(),
                      a -> AttentionSetUtil.createAttentionSetInfo(a, accountLoader)));
    }
    if (has(CUSTOM_KEYED_VALUES)) {
      out.customKeyedValues = cd.customKeyedValues();
    }
    out.hashtags = cd.hashtags();
    out.changeId = in.getKey().get();
    if (in.isNew()) {
      SubmitTypeRecord str = cd.submitTypeRecord();
      if (str.isOk()) {
        out.submitType = str.type;
      }
      if (includeMergeable) {
        out.mergeable = cd.isMergeable();
      }
      if (has(SUBMITTABLE)) {
        out.submittable = submittable(cd);
      }
    }
    if (!has(SKIP_DIFFSTAT)) {
      Optional<ChangedLines> changedLines = cd.changedLines();
      if (changedLines.isPresent()) {
        out.insertions = changedLines.get().insertions;
        out.deletions = changedLines.get().deletions;
      }
    }
    out.isPrivate = in.isPrivate() ? true : null;
    out.workInProgress = in.isWorkInProgress() ? true : null;
    out.hasReviewStarted = in.hasReviewStarted();
    out.subject = in.getSubject();
    out.status = in.getStatus().asChangeStatus();
    out.owner = accountLoader.get(in.getOwner());
    out.setCreated(in.getCreatedOn());
    out.setUpdated(in.getLastUpdatedOn());
    out._number = in.getId().get();

    try (TraceTimer timer =
        TraceContext.newTimer(
            "Count comments", Metadata.builder().changeId(cd.change().getId().get()).build())) {
      out.totalCommentCount = cd.totalCommentCount();
      out.unresolvedCommentCount = cd.unresolvedCommentCount();
    }

    getMetaState(cd).ifPresent(id -> out.metaRevId = id.getName());

    out.reviewed = isReviewedByCurrentUser(cd, user);
    out.starred = isStarredByCurrentUser(cd, user);
    out.labels = labelsJson.labelsFor(accountLoader, cd, has(LABELS), has(DETAILED_LABELS));
    out.requirements = requirementsFor(cd);
    out.submitRecords = submitRecordsFor(cd);
    if (has(SUBMIT_REQUIREMENTS)) {
      out.submitRequirements = submitRequirementsFor(cd);
    }

    if (out.labels != null && has(DETAILED_LABELS)) {
      // If limited to specific patch sets but not the current patch set, don't
      // list permitted labels, since users can't vote on those patch sets.
      if (user.isIdentifiedUser()
          && (!limitToPsId.isPresent() || limitToPsId.get().equals(in.currentPatchSetId()))) {
        out.permittedLabels =
            !cd.change().isAbandoned()
                ? labelsJson.permittedLabels(user.getAccountId(), cd)
                : ImmutableMap.of();
        out.removableLabels = labelsJson.removableLabels(accountLoader, user, cd);
      }
    }

    if (has(LABELS) || has(DETAILED_LABELS)) {
      out.reviewers = reviewerMap(cd.reviewers(), cd.reviewersByEmail(), false);
      out.pendingReviewers = reviewerMap(cd.pendingReviewers(), cd.pendingReviewersByEmail(), true);
      out.removableReviewers = removableReviewers(cd, out);
    }

    setSubmitter(cd, out);

    if (!pluginInfos.isEmpty()) {
      out.plugins = pluginInfos;
    }
    out.revertOf = cd.change().getRevertOf() != null ? cd.change().getRevertOf().get() : null;
    out.submissionId = cd.change().getSubmissionId();
    out.cherryPickOfChange =
        cd.change().getCherryPickOf() != null
            ? cd.change().getCherryPickOf().changeId().get()
            : null;
    out.cherryPickOfPatchSet =
        cd.change().getCherryPickOf() != null ? cd.change().getCherryPickOf().get() : null;

    if (has(REVIEWER_UPDATES)) {
      out.reviewerUpdates = reviewerUpdates(cd);
    }

    boolean needMessages = has(MESSAGES);
    boolean needRevisions = has(ALL_REVISIONS) || has(CURRENT_REVISION) || limitToPsId.isPresent();
    ImmutableMap<PatchSet.Id, PatchSet> src;
    if (needMessages || needRevisions) {
      src = loadPatchSets(cd, limitToPsId);
    } else {
      src = null;
    }

    if (needMessages) {
      out.messages = messages(cd);
    }
    finish(out);

    // This block must come after the ChangeInfo is mostly populated, since
    // it will be passed to ActionVisitors as-is.

    if (needRevisions) {
      out.revisions = revisionJson.getRevisions(accountLoader, cd, src, limitToPsId, out);
      for (Map.Entry<String, RevisionInfo> entry : out.revisions.entrySet()) {
        if (entry.getValue().isCurrent) {
          out.currentRevision = entry.getKey();
          break;
        }
      }
    }

    if (has(CURRENT_ACTIONS) || has(CHANGE_ACTIONS)) {
      actionJson.addChangeActions(out, cd);
    }

    if (has(TRACKING_IDS)) {
      try (TraceTimer timer =
          TraceContext.newTimer(
              "Get tracking IDs", Metadata.builder().changeId(cd.change().getId().get()).build())) {
        ListMultimap<String, String> set = trackingFooters.extract(cd.commitFooters());
        out.trackingIds =
            set.entries().stream()
                .map(e -> new TrackingIdInfo(e.getKey(), e.getValue()))
                .collect(toList());
      }
    }

    out.virtualIdNumber = cd.virtualId().get();

    return out;
  }

  private Map<ReviewerState, Collection<AccountInfo>> reviewerMap(
      ReviewerSet reviewers, ReviewerByEmailSet reviewersByEmail, boolean includeRemoved) {
    try (TraceTimer timer = TraceContext.newTimer("Get reviewer map", Metadata.empty())) {
      Map<ReviewerState, Collection<AccountInfo>> reviewerMap = new HashMap<>();
      for (ReviewerStateInternal state : ReviewerStateInternal.values()) {
        if (!includeRemoved && state == ReviewerStateInternal.REMOVED) {
          continue;
        }
        List<AccountInfo> reviewersByState = toAccountInfo(reviewers.byState(state));
        reviewersByState.addAll(toAccountInfoByEmail(reviewersByEmail.byState(state)));
        if (!reviewersByState.isEmpty()) {
          reviewerMap.put(state.asReviewerState(), reviewersByState);
        }
      }
      return reviewerMap;
    }
  }

  private List<ReviewerUpdateInfo> reviewerUpdates(ChangeData cd) {
    try (TraceTimer timer =
        TraceContext.newTimer(
            "Get reviewer updates",
            Metadata.builder().changeId(cd.change().getId().get()).build())) {
      List<ReviewerStatusUpdate> reviewerUpdates = cd.reviewerUpdates();
      List<ReviewerUpdateInfo> result = new ArrayList<>(reviewerUpdates.size());
      for (ReviewerStatusUpdate c : reviewerUpdates) {
        if (c.reviewer().isPresent()) {
          result.add(
              new ReviewerUpdateInfo(
                  c.date(),
                  accountLoader.get(c.updatedBy()),
                  accountLoader.get(c.reviewer().get()),
                  c.state().asReviewerState()));
        }

        if (c.reviewerByEmail().isPresent()) {
          result.add(
              new ReviewerUpdateInfo(
                  c.date(),
                  accountLoader.get(c.updatedBy()),
                  toAccountInfoByEmail(c.reviewerByEmail().get()),
                  c.state().asReviewerState()));
        }
      }
      return result;
    }
  }

  private boolean submittable(ChangeData cd) {
    try (TraceTimer timer =
        TraceContext.newTimer(
            "Compute submittability",
            Metadata.builder().changeId(cd.change().getId().get()).build())) {
      return cd.submitRequirementsIncludingLegacy().values().stream()
          .allMatch(SubmitRequirementResult::fulfilled);
    }
  }

  private Optional<ObjectId> getMetaState(ChangeData cd) {
    try (TraceTimer timer =
        TraceContext.newTimer(
            "Get change meta ref",
            Metadata.builder().changeId(cd.change().getId().get()).build())) {
      return cd.metaRevision();
    }
  }

  private Boolean isReviewedByCurrentUser(ChangeData cd, CurrentUser user) {
    try (TraceTimer timer =
        TraceContext.newTimer(
            "Get reviewed by", Metadata.builder().changeId(cd.change().getId().get()).build())) {
      return toBoolean(
          cd.change().isNew()
              && has(REVIEWED)
              && user.isIdentifiedUser()
              && cd.isReviewedBy(user.getAccountId()));
    }
  }

  private Boolean isStarredByCurrentUser(ChangeData cd, CurrentUser user) {
    try (TraceTimer timer =
        TraceContext.newTimer(
            "Get starred by", Metadata.builder().changeId(cd.change().getId().get()).build())) {
      return toBoolean(user.isIdentifiedUser() && cd.isStarred(user.getAccountId()));
    }
  }

  private void setSubmitter(ChangeData cd, ChangeInfo out) {
    try (TraceTimer timer =
        TraceContext.newTimer(
            "Set submitter", Metadata.builder().changeId(cd.change().getId().get()).build())) {
      Optional<PatchSetApproval> s = cd.getSubmitApproval();
      if (!s.isPresent()) {
        return;
      }
      out.setSubmitted(s.get().granted(), accountLoader.get(s.get().accountId()));
    }
  }

  private ImmutableList<ChangeMessageInfo> messages(ChangeData cd) {
    try (TraceTimer timer =
        TraceContext.newTimer(
            "Get messages", Metadata.builder().changeId(cd.change().getId().get()).build())) {
      List<ChangeMessage> messages = cmUtil.byChange(cd.notes());
      if (messages.isEmpty()) {
        return ImmutableList.of();
      }

      List<ChangeMessageInfo> result = Lists.newArrayListWithCapacity(messages.size());
      for (ChangeMessage message : messages) {
        result.add(createChangeMessageInfo(message, accountLoader));
      }
      return ImmutableList.copyOf(result);
    }
  }

  private List<AccountInfo> removableReviewers(ChangeData cd, ChangeInfo out)
      throws PermissionBackendException {
    try (TraceTimer timer =
        TraceContext.newTimer(
            "Get removable reviewers",
            Metadata.builder().changeId(cd.change().getId().get()).build())) {
      // Although this is called removableReviewers, this method also determines
      // which CCs are removable.
      //
      // For reviewers, we need to look at each approval, because the reviewer
      // should only be considered removable if *all* of their approvals can be
      // removed. First, add all reviewers with *any* removable approval to the
      // "removable" set. Along the way, if we encounter a non-removable approval,
      // add the reviewer to the "fixed" set. Before we return, remove all members
      // of "fixed" from "removable", because not all of their approvals can be
      // removed.
      Collection<LabelInfo> labels = out.labels.values();
      Set<Account.Id> fixed = Sets.newHashSetWithExpectedSize(labels.size());
      Set<Account.Id> removable = new HashSet<>();

      // Add all reviewers, which will later be removed if they are in the "fixed" set.
      removable.addAll(
          out.reviewers.getOrDefault(ReviewerState.REVIEWER, Collections.emptySet()).stream()
              .filter(a -> a._accountId != null)
              .map(a -> Account.id(a._accountId))
              .collect(Collectors.toSet()));

      // Check if the user has the permission to remove a reviewer. This means we can bypass the
      // testRemoveReviewer check for a specific reviewer in the loop saving potentially many
      // permission checks.
      boolean canRemoveAnyReviewer =
          permissionBackend
              .user(userProvider.get())
              .change(cd)
              .test(ChangePermission.REMOVE_REVIEWER);
      for (LabelInfo label : labels) {
        if (label.all == null) {
          continue;
        }
        for (ApprovalInfo ai : label.all) {
          Account.Id id = Account.id(ai._accountId);

          if (!canRemoveAnyReviewer
              && !removeReviewerControl.testRemoveReviewer(
                  cd, userProvider.get(), id, MoreObjects.firstNonNull(ai.value, 0))) {
            fixed.add(id);
          }
        }
      }

      // CCs are simpler than reviewers. They are removable if the ChangeControl
      // would permit a non-negative approval by that account to be removed, in
      // which case add them to removable. We don't need to add unremovable CCs to
      // "fixed" because we only visit each CC once here.
      Collection<AccountInfo> ccs = out.reviewers.get(ReviewerState.CC);
      if (ccs != null) {
        for (AccountInfo ai : ccs) {
          if (ai._accountId != null) {
            Account.Id id = Account.id(ai._accountId);
            if (canRemoveAnyReviewer
                || removeReviewerControl.testRemoveReviewer(cd, userProvider.get(), id, 0)) {
              removable.add(id);
            }
          }
        }
      }

      // Subtract any reviewers with non-removable approvals from the "removable"
      // set. This also subtracts any CCs that for some reason also hold
      // unremovable approvals.
      removable.removeAll(fixed);

      List<AccountInfo> result = Lists.newArrayListWithCapacity(removable.size());
      for (Account.Id id : removable) {
        result.add(accountLoader.get(id));
      }
      // Reviewers added by email are always removable
      for (Collection<AccountInfo> infos : out.reviewers.values()) {
        for (AccountInfo info : infos) {
          if (info._accountId == null) {
            result.add(info);
          }
        }
      }
      return result;
    }
  }

  private List<AccountInfo> toAccountInfo(Collection<Account.Id> accounts) {
    return accounts.stream()
        .map(accountLoader::get)
        .sorted(AccountInfoComparator.ORDER_NULLS_FIRST)
        .collect(toList());
  }

  private AccountInfo toAccountInfoByEmail(Address address) {
    return new AccountInfo(address.name(), address.email());
  }

  private List<AccountInfo> toAccountInfoByEmail(Collection<Address> addresses) {
    return addresses.stream()
        .map(this::toAccountInfoByEmail)
        .sorted(AccountInfoComparator.ORDER_NULLS_FIRST)
        .collect(toList());
  }

  private ImmutableMap<PatchSet.Id, PatchSet> loadPatchSets(
      ChangeData cd, Optional<PatchSet.Id> limitToPsId) {
    try (TraceTimer timer =
        TraceContext.newTimer(
            "Load patch sets", Metadata.builder().changeId(cd.change().getId().get()).build())) {
      Collection<PatchSet> src;
      if (has(ALL_REVISIONS) || has(MESSAGES)) {
        src = cd.patchSets();
      } else {
        PatchSet ps;
        if (limitToPsId.isPresent()) {
          ps = cd.patchSet(limitToPsId.get());
          if (ps == null) {
            throw new StorageException("missing patch set " + limitToPsId.get());
          }
        } else {
          ps = cd.currentPatchSet();
          if (ps == null) {
            throw new StorageException("missing current patch set for change " + cd.getId());
          }
        }
        src = Collections.singletonList(ps);
      }
      // Sort by patch set ID in increasing order to have a stable output.
      ImmutableSortedMap.Builder<PatchSet.Id, PatchSet> map = ImmutableSortedMap.naturalOrder();
      for (PatchSet patchSet : src) {
        map.put(patchSet.id(), patchSet);
      }
      return map.build();
    }
  }

  /** Populate the 'starred' field. */
  private void populateStarField(List<ChangeInfo> changeInfos) {
    // We populate the 'starred' field for all change infos together so that we open the All-Users
    // repository only once
    try (Repository allUsersRepo = repoManager.openRepository(allUsers)) {
      List<Change.Id> changeIds =
          changeInfos.stream().map(c -> Change.id(c.virtualIdNumber)).collect(Collectors.toList());
      Set<Change.Id> starredChanges =
          starredChangesreader.areStarred(
              allUsersRepo, changeIds, userProvider.get().asIdentifiedUser().getAccountId());
      if (starredChanges.isEmpty()) {
        return;
      }
      changeInfos.stream()
          .forEach(c -> c.starred = starredChanges.contains(Change.id(c.virtualIdNumber)));
    } catch (IOException e) {
      logger.atWarning().withCause(e).log("Failed to open All-Users repo.");
    }
  }

  private ImmutableList<PluginDefinedInfo> getPluginInfos(ChangeData cd) {
    return getPluginInfos(Collections.singleton(cd)).get(cd.getId());
  }

  private ImmutableListMultimap<Change.Id, PluginDefinedInfo> getPluginInfos(
      Collection<ChangeData> cds) {
    if (pluginDefinedInfosFactory.isPresent()) {
      try (TraceTimer timer =
          TraceContext.newTimer(
              "Get plugin infos", Metadata.builder().resourceCount(cds.size()).build())) {
        return pluginDefinedInfosFactory.get().createPluginDefinedInfos(cds);
      }
    }
    return ImmutableListMultimap.of();
  }

  /**
   * Create an empty {@link ChangeInfo} designating a faulty record if {@link
   * ChangeData#hasFailedParsingFromIndex()} is true.
   *
   * <p>Few fields are populated: project, branch, changeId, _number, subject, owner.
   */
  private static Optional<ChangeInfo> createFaultyChangeInfo(ChangeData cd) {
    ChangeInfo info = new ChangeInfo();
    Change c = cd.change();
    if (c == null) {
      return Optional.empty();
    }
    info.project = c.getProject().get();
    info.branch = c.getDest().shortName();
    info.changeId = c.getKey().get();
    info._number = c.getId().get();
    info.subject = "***ERROR***";
    info.owner = new AccountInfo(c.getOwner().get());
    return Optional.of(info);
  }

  @Nullable
  private static Boolean toBoolean(boolean value) {
    return value ? true : null;
  }
}
