// 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.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.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 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.ImmutableListMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
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.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.RefNames;
import com.google.gerrit.entities.SubmitRecord;
import com.google.gerrit.entities.SubmitRecord.Status;
import com.google.gerrit.entities.SubmitRequirement;
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.RefState;
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.StarredChangesUtil;
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.GerritServerConfig;
import com.google.gerrit.server.config.TrackingFooters;
import com.google.gerrit.server.experiments.ExperimentFeatures;
import com.google.gerrit.server.experiments.ExperimentFeaturesConstants;
import com.google.gerrit.server.index.change.ChangeField;
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;

/**
 * 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();

  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 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 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 AccountLoader accountLoader;
  private FixInput fix;

  @Inject
  ChangeJson(
      Provider<CurrentUser> user,
      PermissionBackend permissionBackend,
      ChangeData.Factory cdf,
      AccountLoader.Factory ailf,
      ChangeMessagesUtil cmUtil,
      Provider<ConsistencyChecker> checkerProvider,
      ActionJson actionJson,
      ChangeNotes.Factory notesFactory,
      LabelsJson labelsJson,
      RemoveReviewerControl removeReviewerControl,
      TrackingFooters trackingFooters,
      Metrics metrics,
      RevisionJson.Factory revisionJsonFactory,
      ExperimentFeatures experimentFeatures,
      @GerritServerConfig Config cfg,
      @Assisted Iterable<ListChangesOption> options,
      @Assisted Optional<PluginDefinedInfosFactory> pluginDefinedInfosFactory) {
    this.userProvider = user;
    this.changeDataFactory = cdf;
    this.permissionBackend = permissionBackend;
    this.accountLoaderFactory = ailf;
    this.cmUtil = cmUtil;
    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)
            || lazyloadSubmitRequirements(this.options, experimentFeatures);
    this.pluginDefinedInfosFactory = pluginDefinedInfosFactory;

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

  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 Collection<LegacySubmitRequirementInfo> requirementsFor(ChangeData cd) {
    Collection<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 Collection<SubmitRecordInfo> submitRecordsFor(ChangeData cd) {
    List<SubmitRecordInfo> submitRecordInfos = new ArrayList<>();
    for (SubmitRecord record : cd.submitRecords(SUBMIT_RULE_OPTIONS_STRICT)) {
      submitRecordInfos.add(submitRecordToInfo(record));
    }
    return submitRecordInfos;
  }

  private Collection<SubmitRequirementResultInfo> submitRequirementsFor(ChangeData cd) {
    Collection<SubmitRequirementResultInfo> reqInfos = new ArrayList<>();
    Map<SubmitRequirement, SubmitRequirementResult> requirements = cd.submitRequirements();
    for (Map.Entry<SubmitRequirement, SubmitRequirementResult> entry : requirements.entrySet()) {
      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.id =
        Joiner.on('~')
            .join(Url.encode(info.project), Url.encode(info.branch), Url.encode(info.changeId));
  }

  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(Iterable<ChangeData> all) {
    if (lazyLoad) {
      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);
      }
      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 = i != changes.size() - 1;
        ChangeData cd = changes.get(i);
        ChangeInfo info = cache.get(cd.getId());
        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(Change.id(info._number), 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());
        }
      }
      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.created = c.getCreatedOn();
      info.updated = 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.
      for (ProblemInfo p : out.problems) {
        if (p.status == ProblemInfo.Status.FIXED) {
          cd = changeDataFactory.create(cd.project(), cd.getId());
          break;
        }
      }
    }

    Change in = cd.change();
    out.project = in.getProject().get();
    out.branch = in.getDest().shortName();
    out.topic = in.getTopic();
    if (!cd.attentionSet().isEmpty()) {
      out.attentionSet =
          // This filtering should match GetAttentionSet.
          additionsOnly(cd.attentionSet()).stream()
              .collect(
                  toImmutableMap(
                      a -> a.account().get(),
                      a -> AttentionSetUtil.createAttentionSetInfo(a, accountLoader)));
    }
    out.assignee = in.getAssignee() != null ? accountLoader.get(in.getAssignee()) : null;
    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.created = in.getCreatedOn();
    out.updated = in.getLastUpdatedOn();
    out._number = in.getId().get();
    out.totalCommentCount = cd.totalCommentCount();
    out.unresolvedCommentCount = cd.unresolvedCommentCount();

    if (cd.getRefStates() != null) {
      String metaName = RefNames.changeMetaRef(cd.getId());
      Optional<RefState> metaState =
          cd.getRefStates().values().stream().filter(r -> r.ref().equals(metaName)).findAny();

      // metaState should always be there, but it doesn't hurt to be extra careful.
      metaState.ifPresent(rs -> out.metaRevId = rs.id().getName());
    }

    if (user.isIdentifiedUser()) {
      Collection<String> stars = cd.stars(user.getAccountId());
      out.starred = stars.contains(StarredChangesUtil.DEFAULT_LABEL) ? true : null;
      if (!stars.isEmpty()) {
        out.stars = stars;
      }
    }

    if (in.isNew() && has(REVIEWED) && user.isIdentifiedUser()) {
      out.reviewed = cd.isReviewedBy(user.getAccountId()) ? true : null;
    }

    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();
      }
    }

    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();
    Map<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);
      if (out.revisions != null) {
        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)) {
      ListMultimap<String, String> set = trackingFooters.extract(cd.commitFooters());
      out.trackingIds =
          set.entries().stream()
              .map(e -> new TrackingIdInfo(e.getKey(), e.getValue()))
              .collect(toList());
    }

    return out;
  }

  private Map<ReviewerState, Collection<AccountInfo>> reviewerMap(
      ReviewerSet reviewers, ReviewerByEmailSet reviewersByEmail, boolean includeRemoved) {
    Map<ReviewerState, Collection<AccountInfo>> reviewerMap = new HashMap<>();
    for (ReviewerStateInternal state : ReviewerStateInternal.values()) {
      if (!includeRemoved && state == ReviewerStateInternal.REMOVED) {
        continue;
      }
      Collection<AccountInfo> reviewersByState = toAccountInfo(reviewers.byState(state));
      reviewersByState.addAll(toAccountInfoByEmail(reviewersByEmail.byState(state)));
      if (!reviewersByState.isEmpty()) {
        reviewerMap.put(state.asReviewerState(), reviewersByState);
      }
    }
    return reviewerMap;
  }

  private Collection<ReviewerUpdateInfo> reviewerUpdates(ChangeData cd) {
    List<ReviewerStatusUpdate> reviewerUpdates = cd.reviewerUpdates();
    List<ReviewerUpdateInfo> result = new ArrayList<>(reviewerUpdates.size());
    for (ReviewerStatusUpdate c : reviewerUpdates) {
      ReviewerUpdateInfo change = new ReviewerUpdateInfo();
      change.updated = c.date();
      change.state = c.state().asReviewerState();
      change.updatedBy = accountLoader.get(c.updatedBy());
      change.reviewer = accountLoader.get(c.reviewer());
      result.add(change);
    }
    return result;
  }

  private boolean submittable(ChangeData cd) {
    return SubmitRecord.allRecordsOK(cd.submitRecords(SUBMIT_RULE_OPTIONS_STRICT));
  }

  private void setSubmitter(ChangeData cd, ChangeInfo out) {
    Optional<PatchSetApproval> s = cd.getSubmitApproval();
    if (!s.isPresent()) {
      return;
    }
    out.submitted = s.get().granted();
    out.submitter = accountLoader.get(s.get().accountId());
  }

  private Collection<ChangeMessageInfo> messages(ChangeData cd) {
    List<ChangeMessage> messages = cmUtil.byChange(cd.notes());
    if (messages.isEmpty()) {
      return Collections.emptyList();
    }

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

  private Collection<AccountInfo> removableReviewers(ChangeData cd, ChangeInfo out)
      throws PermissionBackendException {
    // 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 Collection<AccountInfo> toAccountInfo(Collection<Account.Id> accounts) {
    return accounts.stream()
        .map(accountLoader::get)
        .sorted(AccountInfoComparator.ORDER_NULLS_FIRST)
        .collect(toList());
  }

  private Collection<AccountInfo> toAccountInfoByEmail(Collection<Address> addresses) {
    return addresses.stream()
        .map(a -> new AccountInfo(a.name(), a.email()))
        .sorted(AccountInfoComparator.ORDER_NULLS_FIRST)
        .collect(toList());
  }

  private Map<PatchSet.Id, PatchSet> loadPatchSets(
      ChangeData cd, Optional<PatchSet.Id> limitToPsId) {
    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);
    }
    Map<PatchSet.Id, PatchSet> map = Maps.newHashMapWithExpectedSize(src.size());
    for (PatchSet patchSet : src) {
      map.put(patchSet.id(), patchSet);
    }
    return map;
  }

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

  private ImmutableListMultimap<Change.Id, PluginDefinedInfo> getPluginInfos(
      Collection<ChangeData> cds) {
    if (pluginDefinedInfosFactory.isPresent()) {
      return pluginDefinedInfosFactory.get().createPluginDefinedInfos(cds);
    }
    return ImmutableListMultimap.of();
  }

  private static boolean lazyloadSubmitRequirements(
      Set<ListChangesOption> changeOptions, ExperimentFeatures experimentFeatures) {
    // TODO(ghareeb,hiesel): Remove this method.
    // We are testing the new submit requirements with users in lieu of upgrading the change index
    // to a version that supports the new requirements.
    // Upgrading now, before the feature is finalized would be counter productive, because the index
    // format might change while we iterate over the feature.
    // Allowing changes to lazyload parameters will slow down dashboards for users who have this
    // feature enabled, but will backfill submit requirements that weren't loaded from the index by
    // simply computing them.
    return changeOptions.contains(SUBMIT_REQUIREMENTS)
        && experimentFeatures.isFeatureEnabled(
            ExperimentFeaturesConstants
                .GERRIT_BACKEND_REQUEST_FEATURE_ENABLE_SUBMIT_REQUIREMENTS_BACKFILLING_ON_DASHBOARD);
  }
}
