// 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.googlesource.gerrit.plugins.github.filters;

import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.gerrit.reviewdb.client.AccountExternalId;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.account.AccountState;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import com.googlesource.gerrit.plugins.github.oauth.GitHubLogin;
import com.googlesource.gerrit.plugins.github.oauth.GitHubOAuthConfig;
import com.googlesource.gerrit.plugins.github.oauth.OAuthFilter;
import com.googlesource.gerrit.plugins.github.oauth.OAuthProtocol;
import com.googlesource.gerrit.plugins.github.oauth.OAuthProtocol.AccessToken;
import com.googlesource.gerrit.plugins.github.oauth.OAuthWebFilter;
import com.googlesource.gerrit.plugins.github.oauth.OAuthProtocol.Scope;
import com.googlesource.gerrit.plugins.github.oauth.ScopedProvider;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Singleton
public class GitHubOAuthFilter implements Filter {
  private Logger LOG = LoggerFactory.getLogger(GitHubOAuthFilter.class);

  private final ScopedProvider<GitHubLogin> loginProvider;
  private final Scope[] authScopes;
  private final OAuthProtocol oauth;
  private final GitHubOAuthConfig config;
  private final Provider<CurrentUser> userProvider;
  private final AccountCache accountCache;

  @Inject
  public GitHubOAuthFilter(ScopedProvider<GitHubLogin> loginProvider,
      GitHubOAuthConfig githubOAuthConfig, 
      OAuthProtocol oauth, 
      Provider<CurrentUser> userProvider,
      AccountCache accountCache) {
    this.loginProvider = loginProvider;
    this.authScopes = githubOAuthConfig.getDefaultScopes();
    this.oauth = oauth;
    this.config = githubOAuthConfig;
    this.userProvider = userProvider;
    this.accountCache = accountCache;
  }

  @Override
  public void init(FilterConfig filterConfig) throws ServletException {
  }

  @Override
  public void doFilter(ServletRequest request, ServletResponse response,
      FilterChain chain) throws IOException, ServletException {
    GitHubLogin hubLogin = loginProvider.get((HttpServletRequest) request);
    LOG.debug("GitHub login: " + hubLogin);
    CurrentUser user = userProvider.get();
    if (!hubLogin.isLoggedIn()
        && !OAuthFilter.skipOAuth((HttpServletRequest) request)
        && user.isIdentifiedUser()) {
      AccountExternalId gitHubExtId = getGitHubExternalId(user);

      String oauthToken =
          gitHubExtId.getSchemeRest()
              .substring(OAuthWebFilter.GITHUB_EXT_ID.length());
      hubLogin.login(new AccessToken(oauthToken));
    }

    chain.doFilter(request, response);
  }

  private AccountExternalId getGitHubExternalId(CurrentUser user) {
    Collection<AccountExternalId> accountExtIds =
        accountCache.get(((IdentifiedUser) user).getAccountId())
            .getExternalIds();
    Collection<AccountExternalId> gitHubExtId =
        Collections2.filter(accountExtIds,
            new Predicate<AccountExternalId>() {
              @Override
              public boolean apply(AccountExternalId externalId) {
                return externalId.isScheme(AccountExternalId.SCHEME_EXTERNAL)
                    && externalId.getSchemeRest().startsWith(
                        OAuthWebFilter.GITHUB_EXT_ID);
              }
            });

    if (gitHubExtId.isEmpty()) {
      throw new IllegalStateException("Current Gerrit user "
          + user.getUserName() + " has no GitHub OAuth external ID");
    }
    return gitHubExtId.iterator().next();
  }

  @Override
  public void destroy() {
  }

}
