// Copyright (C) 2009 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.httpd;

import static java.util.concurrent.TimeUnit.HOURS;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.UsedAt;
import com.google.gerrit.entities.Account;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.httpd.restapi.ParameterParser;
import com.google.gerrit.server.AccessPath;
import com.google.gerrit.server.AnonymousUser;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.PropertyMap;
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.account.AuthResult;
import com.google.gerrit.server.account.externalids.ExternalId;
import com.google.gerrit.server.config.AuthConfig;
import com.google.inject.Provider;
import java.util.EnumSet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jgit.http.server.GitSmartHttpTools;

public abstract class CacheBasedWebSession extends WebSession {
  @VisibleForTesting public static final String ACCOUNT_COOKIE = "GerritAccount";

  @UsedAt(UsedAt.Project.PLUGIN_WEBSESSION_FLATFILE)
  public static final long MAX_AGE_MINUTES = HOURS.toMinutes(12);

  private final HttpServletRequest request;
  private final HttpServletResponse response;
  private final WebSessionManager manager;
  private final AuthConfig authConfig;
  private final Provider<AnonymousUser> anonymousProvider;
  private final IdentifiedUser.RequestFactory identified;
  private final EnumSet<AccessPath> okPaths = EnumSet.of(AccessPath.UNKNOWN);
  private final AccountCache byIdCache;
  private Cookie outCookie;

  private WebSessionManager.Key key;
  private WebSessionManager.Val val;
  private CurrentUser user;

  protected CacheBasedWebSession(
      HttpServletRequest request,
      HttpServletResponse response,
      WebSessionManager manager,
      AuthConfig authConfig,
      Provider<AnonymousUser> anonymousProvider,
      IdentifiedUser.RequestFactory identified,
      AccountCache byIdCache) {
    this.request = request;
    this.response = response;
    this.manager = manager;
    this.authConfig = authConfig;
    this.anonymousProvider = anonymousProvider;
    this.identified = identified;
    this.byIdCache = byIdCache;

    String cookie = readCookie(request);
    if (cookie != null) {
      authFromCookie(cookie);
    } else if (request.getRequestURI() == null || !GitSmartHttpTools.isGitClient(request)) {
      String token;
      try {
        token = ParameterParser.getQueryParams(request).accessToken();
      } catch (BadRequestException e) {
        token = null;
      }
      if (token != null) {
        authFromQueryParameter(token);
      }
    }
    if (val != null && !checkAccountStatus(val.getAccountId())) {
      val = null;
      okPaths.clear();
    }
    if (val != null && val.needsCookieRefresh()) {
      // Session is more than half old; update cache entry with new expiration date.
      val = manager.createVal(key, val);
    }
  }

  private void authFromCookie(String cookie) {
    key = new WebSessionManager.Key(cookie);
    val = manager.get(key);
    String token = request.getHeader(XsrfConstants.XSRF_HEADER_NAME);
    if (val != null && token != null && token.equals(val.getAuth())) {
      okPaths.add(AccessPath.REST_API);
    }
  }

  private void authFromQueryParameter(String accessToken) {
    key = new WebSessionManager.Key(accessToken);
    val = manager.get(key);
    if (val != null) {
      okPaths.add(AccessPath.REST_API);
    }
  }

  private static String readCookie(HttpServletRequest request) {
    Cookie[] all = request.getCookies();
    if (all != null) {
      for (Cookie c : all) {
        if (ACCOUNT_COOKIE.equals(c.getName())) {
          return Strings.emptyToNull(c.getValue());
        }
      }
    }
    return null;
  }

  @Override
  public boolean isSignedIn() {
    return val != null;
  }

  @Override
  @Nullable
  public String getXGerritAuth() {
    return isSignedIn() ? val.getAuth() : null;
  }

  @Override
  public boolean isValidXGerritAuth(String keyIn) {
    return keyIn.equals(getXGerritAuth());
  }

  @Override
  public boolean isAccessPathOk(AccessPath path) {
    return okPaths.contains(path);
  }

  @Override
  public void setAccessPathOk(AccessPath path, boolean ok) {
    if (ok) {
      okPaths.add(path);
    } else {
      okPaths.remove(path);
    }
  }

  @Override
  public CurrentUser getUser() {
    if (user == null) {
      if (isSignedIn()) {

        user = identified.create(val.getAccountId(), getUserProperties(val));
      } else {
        user = anonymousProvider.get();
      }
    }
    return user;
  }

  private static PropertyMap getUserProperties(@Nullable WebSessionManager.Val val) {
    if (val == null || val.getExternalId() == null) {
      return PropertyMap.EMPTY;
    }
    return PropertyMap.builder()
        .put(CurrentUser.LAST_LOGIN_EXTERNAL_ID_PROPERTY_KEY, val.getExternalId())
        .build();
  }

  @Override
  public void login(AuthResult res, boolean rememberMe) {
    Account.Id id = res.getAccountId();
    ExternalId.Key identity = res.getExternalId();

    if (val != null) {
      manager.destroy(key);
    }

    if (!checkAccountStatus(id)) {
      val = null;
      return;
    }

    key = manager.createKey(id);
    val = manager.createVal(key, id, rememberMe, identity, null, null);
    saveCookie();
    user = identified.create(val.getAccountId(), getUserProperties(val));
  }

  /** Set the user account for this current request only. */
  @Override
  public void setUserAccountId(Account.Id id) {
    key = new WebSessionManager.Key("id:" + id);
    val = new WebSessionManager.Val(id, 0, false, null, 0, null, null);
    user = identified.runAs(id, user, PropertyMap.EMPTY);
  }

  @Override
  public void logout() {
    if (val != null) {
      manager.destroy(key);
      key = null;
      val = null;
      saveCookie();
      user = anonymousProvider.get();
    }
  }

  @Override
  public String getSessionId() {
    return val != null ? val.getSessionId() : null;
  }

  private boolean checkAccountStatus(Account.Id id) {
    return byIdCache.get(id).filter(as -> as.account().isActive()).isPresent();
  }

  private void saveCookie() {
    if (response == null) {
      return;
    }

    final String token;
    final int ageSeconds;

    if (key == null) {
      token = "";
      ageSeconds = 0 /* erase at client */;
    } else {
      token = key.getToken();
      ageSeconds = manager.getCookieAge(val);
    }

    String path = authConfig.getCookiePath();
    if (Strings.isNullOrEmpty(path)) {
      path = request.getContextPath();
      if (Strings.isNullOrEmpty(path)) {
        path = "/";
      }
    }

    if (outCookie != null) {
      throw new IllegalStateException("Cookie " + ACCOUNT_COOKIE + " was set");
    }

    outCookie = new Cookie(ACCOUNT_COOKIE, token);

    String domain = authConfig.getCookieDomain();
    if (!Strings.isNullOrEmpty(domain)) {
      outCookie.setDomain(domain);
    }

    outCookie.setSecure(isSecure(request));
    outCookie.setPath(path);
    outCookie.setMaxAge(ageSeconds);
    outCookie.setSecure(authConfig.getCookieSecure());
    response.addCookie(outCookie);
  }

  private static boolean isSecure(HttpServletRequest req) {
    return req.isSecure() || "https".equals(req.getScheme());
  }
}
