// Copyright (C) 2017 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.googlesource.gerrit.plugins.quota;

import static com.googlesource.gerrit.plugins.quota.Module.CACHE_NAME_ACCOUNTID;
import static com.googlesource.gerrit.plugins.quota.Module.CACHE_NAME_REMOTEHOST;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.cache.LoadingCache;
import com.google.common.util.concurrent.RateLimiter;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.git.validators.UploadValidationListener;
import com.google.gerrit.server.validators.ValidationException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.name.Named;

import com.googlesource.gerrit.plugins.quota.Module.Holder;

import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.transport.UploadPack;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.MessageFormat;
import java.util.Collection;
import java.util.concurrent.ExecutionException;

public class RateLimitUploadListener implements UploadValidationListener {
  private static final int SECONDS_PER_HOUR = 3600;
  private static final Logger log =
      LoggerFactory.getLogger(RateLimitUploadListener.class);
  private static final Method createStopwatchMethod;
  private static final Constructor<?> constructor;

  static {
    try {
      Class<?> sleepingStopwatchClass = Class.forName(
          "com.google.common.util.concurrent.RateLimiter$SleepingStopwatch");
      createStopwatchMethod =
          sleepingStopwatchClass.getDeclaredMethod("createFromSystemTimer");
      createStopwatchMethod.setAccessible(true);
      Class<?> burstyRateLimiterClass = Class.forName(
          "com.google.common.util.concurrent.SmoothRateLimiter$SmoothBursty");
      constructor = burstyRateLimiterClass.getDeclaredConstructors()[0];
      constructor.setAccessible(true);
    } catch (ClassNotFoundException | NoSuchMethodException e) {
      // shouldn't happen
      throw new RuntimeException(
          "Failed to prepare loading RateLimiter via reflection", e);
    }
  }

  /**
   * Create a custom instance of RateLimiter by accessing the non-public
   * constructor of the implementation class SmoothRateLimiter.SmoothBursty
   * through reflection.
   *
   * <p>
   * RateLimiter's implementation class SmoothRateLimiter.SmoothBursty allows to
   * collect permits during idle times which can be used to send bursts of
   * requests exceeding the average rate until the stored permits are consumed.
   * If the rate per second is 0.2 and you wait 20 seconds you can acquire 4
   * permits which in average matches the configured rate limit of 0.2
   * requests/second. If the permitted rate is smaller than 1 per second the
   * standard implementation doesn't allow any bursts since it hard-codes the
   * maximum time which can be used to collect stored permits to 1 second.
   *
   * <p>
   * Build jobs fetching updates from Gerrit are typically triggered by events
   * which can arrive in bursts. Hence the standard RateLimiter seems not to be
   * the right choice at least for fetch requests where we probably want to
   * limit the rate to less than 1 request per second per user.
   *
   * <p>
   * The used constructor can't be accessed through a public method yet hence
   * use reflection to instantiate it.
   *
   * @see "https://github.com/google/guava/issues/1974"
   * @param permitsPerSecond the new stable rate of this {@code RateLimiter}
   * @param maxBurstSeconds The maximum number of permits that can be saved.
   * @return a new RateLimiter
   */
  @VisibleForTesting
  static RateLimiter createSmoothBurstyRateLimiter(double permitsPerSecond,
      double maxBurstSeconds) {
    RateLimiter rl;
    try {
      Object stopwatch = createStopwatchMethod.invoke(null);
      rl = (RateLimiter) constructor.newInstance(stopwatch, maxBurstSeconds);
      rl.setRate(permitsPerSecond);
    } catch (InvocationTargetException | IllegalAccessException
        | InstantiationException e) {
      // shouldn't happen
      throw new RuntimeException(e);
    }
    return rl;
  }

  private final Provider<CurrentUser> user;
  private final LoadingCache<Account.Id, Holder> limitsPerAccount;
  private final LoadingCache<String, Holder> limitsPerRemoteHost;

  @Inject
  RateLimitUploadListener(Provider<CurrentUser> user,
      @Named(CACHE_NAME_ACCOUNTID) LoadingCache<Account.Id, Holder> limitsPerAccount,
      @Named(CACHE_NAME_REMOTEHOST) LoadingCache<String, Holder> limitsPerRemoteHost) {
    this.user = user;
    this.limitsPerAccount = limitsPerAccount;
    this.limitsPerRemoteHost = limitsPerRemoteHost;
  }

  @Override
  public void onBeginNegotiate(Repository repository, Project project,
      String remoteHost, UploadPack up, Collection<? extends ObjectId> wants,
      int cntOffered) throws ValidationException {
    RateLimiter limiter = null;
    CurrentUser u = user.get();
    if (u.isIdentifiedUser()) {
      Account.Id accountId = u.asIdentifiedUser().getAccountId();
      try {
        limiter = limitsPerAccount.get(accountId).get();
      } catch (ExecutionException e) {
        String msg = MessageFormat
            .format("Cannot get rate limits for account ''{}''", accountId);
        log.warn(msg, e);
      }
    } else {
      try {
        limiter = limitsPerRemoteHost.get(remoteHost).get();
      } catch (ExecutionException e) {
        String msg = MessageFormat.format(
            "Cannot get rate limits for anonymous access from remote host ''{0}''",
            remoteHost);
        log.warn(msg, e);
      }
    }
    if (limiter != null && !limiter.tryAcquire()) {
      throw new RateLimitException(
          MessageFormat.format("Exceeded rate limit of {0,number,##.##} fetch requests/hour",
              limiter.getRate() * SECONDS_PER_HOUR));
    }
  }

  @Override
  public void onPreUpload(Repository repository, Project project,
      String remoteHost, UploadPack up, Collection<? extends ObjectId> wants,
      Collection<? extends ObjectId> haves) throws ValidationException {
  }
}
