// Copyright (C) 2013 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.util.http;

import static java.util.concurrent.TimeUnit.DAYS;
import static java.util.concurrent.TimeUnit.SECONDS;

import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/** Utilities to manage HTTP caching directives in responses. */
public class CacheHeaders {
  private static final long MAX_CACHE_DURATION = DAYS.toSeconds(365);

  /**
   * Do not cache the response, anywhere.
   *
   * @param res response being returned.
   */
  public static void setNotCacheable(HttpServletResponse res) {
    String cc = "no-cache, no-store, max-age=0, must-revalidate";
    res.setHeader("Cache-Control", cc);
    res.setHeader("Pragma", "no-cache");
    res.setHeader("Expires", "Mon, 01 Jan 1990 00:00:00 GMT");
    res.setDateHeader("Date", System.currentTimeMillis());
  }

  /**
   * Permit caching the response for up to the age specified.
   *
   * <p>If the request is on a secure connection (e.g. SSL) private caching is used. This allows the
   * user-agent to cache the response, but requests intermediate proxies to not cache. This may
   * offer better protection for Set-Cookie headers.
   *
   * <p>If the request is on plaintext (insecure), public caching is used. This may allow an
   * intermediate proxy to cache the response, including any Set-Cookie header that may have also
   * been included.
   *
   * @param req current request.
   * @param res response being returned.
   * @param age how long the response can be cached.
   * @param unit time unit for age, usually {@link TimeUnit#SECONDS}.
   */
  public static void setCacheable(
      HttpServletRequest req, HttpServletResponse res, long age, TimeUnit unit) {
    setCacheable(req, res, age, unit, false);
  }

  /**
   * Permit caching the response for up to the age specified.
   *
   * <p>If the request is on a secure connection (e.g. SSL) private caching is used. This allows the
   * user-agent to cache the response, but requests intermediate proxies to not cache. This may
   * offer better protection for Set-Cookie headers.
   *
   * <p>If the request is on plaintext (insecure), public caching is used. This may allow an
   * intermediate proxy to cache the response, including any Set-Cookie header that may have also
   * been included.
   *
   * @param req current request.
   * @param res response being returned.
   * @param age how long the response can be cached.
   * @param unit time unit for age, usually {@link TimeUnit#SECONDS}.
   * @param mustRevalidate true if the client must validate the cached entity.
   */
  public static void setCacheable(
      HttpServletRequest req,
      HttpServletResponse res,
      long age,
      TimeUnit unit,
      boolean mustRevalidate) {
    if (req.isSecure()) {
      setCacheablePrivate(res, age, unit, mustRevalidate);
    } else {
      setCacheablePublic(res, age, unit, mustRevalidate);
    }
  }

  /**
   * Allow the response to be cached by proxies and user-agents.
   *
   * <p>If the response includes a Set-Cookie header the cookie may be cached by a proxy and
   * returned to multiple browsers behind the same proxy. This is insecure for authenticated
   * connections.
   *
   * @param res response being returned.
   * @param age how long the response can be cached.
   * @param unit time unit for age, usually {@link TimeUnit#SECONDS}.
   * @param mustRevalidate true if the client must validate the cached entity.
   */
  public static void setCacheablePublic(
      HttpServletResponse res, long age, TimeUnit unit, boolean mustRevalidate) {
    long now = System.currentTimeMillis();
    long sec = maxAgeSeconds(age, unit);

    res.setDateHeader("Expires", now + SECONDS.toMillis(sec));
    res.setDateHeader("Date", now);
    cache(res, "public", age, unit, mustRevalidate);
  }

  /**
   * Allow the response to be cached only by the user-agent.
   *
   * @param res response being returned.
   * @param age how long the response can be cached.
   * @param unit time unit for age, usually {@link TimeUnit#SECONDS}.
   * @param mustRevalidate true if the client must validate the cached entity.
   */
  public static void setCacheablePrivate(
      HttpServletResponse res, long age, TimeUnit unit, boolean mustRevalidate) {
    long now = System.currentTimeMillis();
    res.setDateHeader("Expires", now);
    res.setDateHeader("Date", now);
    cache(res, "private", age, unit, mustRevalidate);
  }

  public static boolean hasCacheHeader(HttpServletResponse res) {
    return res.containsHeader("Cache-Control") || res.containsHeader("Expires");
  }

  private static void cache(
      HttpServletResponse res, String type, long age, TimeUnit unit, boolean revalidate) {
    res.setHeader(
        "Cache-Control",
        String.format(
            "%s, max-age=%d%s",
            type, maxAgeSeconds(age, unit), revalidate ? ", must-revalidate" : ""));
  }

  private static long maxAgeSeconds(long age, TimeUnit unit) {
    return Math.min(unit.toSeconds(age), MAX_CACHE_DURATION);
  }

  private CacheHeaders() {}
}
