// Copyright (C) 2010 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.git.receive;

import static com.google.common.collect.ImmutableList.toImmutableList;

import com.google.common.collect.Sets;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.server.git.HookUtil;
import com.google.gerrit.server.index.change.ChangeField;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.InternalChangeQuery;
import com.google.gerrit.server.util.MagicBranch;
import com.google.inject.Provider;
import java.io.IOException;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.transport.AdvertiseRefsHook;
import org.eclipse.jgit.transport.ReceivePack;
import org.eclipse.jgit.transport.ServiceMayNotContinueException;
import org.eclipse.jgit.transport.UploadPack;

/**
 * Exposes only the non refs/changes/ reference names and provide additional haves.
 *
 * <p>Negotiation on Git push is suboptimal in that it tends to send more objects to the server than
 * it should. This results in increased latencies for {@code git push}.
 *
 * <p>Ref advertisement for Git pushes still works in a "the server speaks first fashion" as Git
 * Protocol V2 only addressed fetches Therefore the server needs to send all available references.
 * For large repositories, this can be in the tens of megabytes to send to the client. We therefore
 * remove all refs in refs/changes/* to scale down that footprint. Trivially, this would increase
 * the unnecessary objects that the client has to send to the server because the common ancestor it
 * finds in negotiation might be further back in history.
 *
 * <p>To work around this, we advertise the last 32 changes in that repository as additional {@code
 * .haves}. This is a heuristical approach that aims at scaling down the number of unnecessary
 * objects that client sends to the server. Unnecessary here refers to objects that the server
 * already has.
 *
 * <p>TODO(hiesel): Instrument this heuristic and proof its value.
 */
public class ReceiveCommitsAdvertiseRefsHook implements AdvertiseRefsHook {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private final Provider<InternalChangeQuery> queryProvider;
  private final Project.NameKey projectName;

  public ReceiveCommitsAdvertiseRefsHook(
      Provider<InternalChangeQuery> queryProvider, Project.NameKey projectName) {
    this.queryProvider = queryProvider;
    this.projectName = projectName;
  }

  @Override
  public void advertiseRefs(UploadPack us) {
    throw new UnsupportedOperationException(
        "ReceiveCommitsAdvertiseRefsHook cannot be used for UploadPack");
  }

  @Override
  public void advertiseRefs(ReceivePack rp) throws ServiceMayNotContinueException {
    Map<String, Ref> advertisedRefs = HookUtil.ensureAllRefsAdvertised(rp);
    advertisedRefs.keySet().stream()
        .filter(ReceiveCommitsAdvertiseRefsHook::skip)
        .collect(toImmutableList())
        .forEach(r -> advertisedRefs.remove(r));
    rp.setAdvertisedRefs(advertisedRefs, advertiseOpenChanges(rp.getRepository()));
  }

  private Set<ObjectId> advertiseOpenChanges(Repository repo)
      throws ServiceMayNotContinueException {
    // Advertise some recent open changes, in case a commit is based on one.
    int limit = 32;
    try {
      Set<ObjectId> r = Sets.newHashSetWithExpectedSize(limit);
      for (ChangeData cd :
          queryProvider
              .get()
              .setRequestedFields(
                  // Required for ChangeIsVisibleToPrdicate.
                  ChangeField.CHANGE,
                  ChangeField.REVIEWER,
                  // Required during advertiseOpenChanges.
                  ChangeField.PATCH_SET)
              .enforceVisibility(true)
              .setLimit(limit)
              .byProjectOpen(projectName)) {
        PatchSet ps = cd.currentPatchSet();
        if (ps != null) {
          // Ensure we actually observed a patch set ref pointing to this
          // object, in case the database is out of sync with the repo and the
          // object doesn't actually exist.
          try {
            Ref psRef = repo.getRefDatabase().exactRef(RefNames.patchSetRef(ps.id()));
            if (psRef != null) {
              r.add(ps.commitId());
            }
          } catch (IOException e) {
            throw new ServiceMayNotContinueException(e);
          }
        }
      }

      return r;
    } catch (StorageException err) {
      logger.atSevere().withCause(err).log("Cannot list open changes of %s", projectName);
      return Collections.emptySet();
    }
  }

  private static boolean skip(String name) {
    return name.startsWith(RefNames.REFS_CHANGES)
        || name.startsWith(RefNames.REFS_CACHE_AUTOMERGE)
        || MagicBranch.isMagicBranch(name);
  }
}
