package com.googlesource.gerrit.plugins.github.oauth;

import com.google.common.base.Charsets;
import com.google.common.base.Strings;
import com.google.common.io.BaseEncoding;
import com.google.common.io.CharStreams;
import com.google.gson.Gson;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import lombok.Getter;

import com.google.gerrit.extensions.auth.oauth.OAuthToken;
import com.google.gerrit.extensions.auth.oauth.OAuthVerifier;

@Singleton
public class OAuthProtocol {
  /**
   * Supported OAuth Scopes.
   *
   * OAuth authorization scopes as defined in GitHub API at:
   * https://developer.github.com/v3/oauth/#scopes
   */
  public static enum Scope {
    /**
     * Grants read-only access to public information (includes public user
     * profile info, public repository info, and gists)
     */
    DEFAULT("", "Read-only public information"),

    /**
     * Grants read/write access to profile info only. Note that this scope
     * includes user:email and user:follow.
     */
    USER("user", "Read/write profile info"),

    /**
     * Grants read access to a user’s email addresses.
     */
    USER_EMAIL("user:email", "Read-only user's e-mail"),

    /**
     * Grants access to follow or unfollow other users.
     */
    USER_FOLLOW("user:follow", "(Un)Follow users"),

    /**
     * Grants read/write access to code, commit statuses, collaborators, and
     * deployment statuses for public repositories. Also
     * required for starring public repositories.
     */
    PUBLIC_REPO("public_repo", "Read/write to public repositories"),

    /**
     * Grants read/write access to code, commit statuses, collaborators, and
     * deployment statuses for public and private repositories and
     * organizations.
     */
    REPO("repo", "Read/write to all public/private repositories"),

    /**
     * Grants access to deployment statuses for public and private repositories.
     * This scope is only necessary to grant other users or services access to
     * deployment statuses, without granting access to the code.
     */
    REPO_DEPLOYMENT("repo_deployment", "Read-only deployment statuses"),

    /**
     * Grants read/write access to public and private repository commit
     * statuses. This scope is only necessary to grant other users or services
     * access to private repository commit statuses without granting access to
     * the code.
     */
    REPO_STATUS("repo:status", "Read/write commit statuses"),

    /**
     * Grants access to delete admin-able repositories.
     */
    DELETE_REPO("delete_repo", "Delete repositories"),

    /**
     * Grants read access to a user’s notifications. repo also provides this
     * access.
     */
    NOTIFICATIONS("notifications", "Read user's notifications"),

    /**
     * Grants write access to gists.
     */
    GIST("gist", "Write Gists"),

    /**
     * Grants read and ping access to hooks in public or private repositories.
     */
    READ_REPO_HOOK("read:repo_hook",
        "Read/ping public/private repositories' hooks"),

    /**
     * Grants read, write, and ping access to hooks in public or private
     * repositories.
     */
    WRITE_REPO_HOOK("write:repo_hook",
        "Read/write/ping public/private repositories' hooks"),

    /**
     * Grants read, write, ping, and delete access to hooks in public or private
     * repositories.
     */
    ADMIN_REPO_HOOK("admin:repo_hook",
        "Read/write/ping/delete access to public/private repositories' hooks"),

    /**
     * Grants read, write, ping, and delete access to organization hooks. Note:
     * OAuth tokens will only be able to perform these actions on organization
     * hooks which were created by the OAuth application. Personal access tokens
     * will only be able to perform these actions on organization hooks created
     * by a user.
     */
    ADMIN_ORG_HOOK("admin:org_hook",
        "Read/write/ping/delete access to public/private organizations' hooks"),

    /**
     * Read-only access to organization, teams, and membership.
     */
    READ_ORG("read:org", "Read-only organizations"),

    /**
     * Publicize and un-publicize organization membership.
     */
    WRITE_ORG("write:org", "(Un)Publicize organizations membership"),

    /**
     * Fully manage organization, teams, and memberships.
     */
    ADMIN_ORG("admin:org", "Manage organizations, teams and memberships"),

    /**
     * List and view details for public keys.
     */
    READ_PUBLIC_KEY("read:public_key", "Read-only user's public keys"),

    /**
     * Create, list, and view details for public keys.
     */
    WRITE_PUBLIC_KEY("write:public_key", "Read/write/list user's public keys"),

    /**
     * Fully manage public keys.
     */
    ADMIN_PUBLIC_KEY("admin:public_key", "Fully manage user's public keys");

    @Getter
    private final String value;

    @Getter
    private final String description;

    private Scope(final String value, final String description) {
      this.value = value;
      this.description = description;
    }
  }
  private static final String ME_SEPARATOR = ",";
  private static final Logger log = LoggerFactory
      .getLogger(OAuthProtocol.class);
  private static final String FINAL_URL_PARAM = "final";
  private static SecureRandom randomState = newRandomGenerator();

  private final GitHubOAuthConfig config;
  private final Gson gson;
  private final Provider<HttpClient> httpProvider;

  public static class AccessToken {
    public String accessToken;
    public String tokenType;
    public String error;
    public String errorDescription;
    public String errorUri;
    public String raw;

    public AccessToken() {
    }

    public AccessToken(String token) {
      this(token, "");
    }

    public AccessToken(String token, String type) {
      this();
      this.accessToken = token;
      this.tokenType = type;
    }

    @Override
    public String toString() {
      if (isError()) {
        return "Error AccessToken [error=" + error + ", error_description="
            + errorDescription + ", error_uri=" + errorUri + "]";
      } else {
        return "AccessToken [access_token=" + accessToken + ", token_type="
            + tokenType + "]";
      }
    }

    @Override
    public int hashCode() {
      return Objects.hash(accessToken, tokenType, error, errorDescription,
          errorUri);
    }

    @Override
    public boolean equals(Object obj) {
      return Objects.deepEquals(this, obj);
    }

    public boolean isError() {
      return !Strings.isNullOrEmpty(error);
    }

    public String getRaw() {
      return raw;
    }

    public void setRaw(String raw) {
      this.raw = raw;
    }

    public OAuthToken toOAuthToken() {
      return new OAuthToken(accessToken, null, getRaw());
    }
  }

  @Inject
  public OAuthProtocol(GitHubOAuthConfig config,
      PooledHttpClientProvider httpClientProvider,
      /*
       * We need to explicitly tell Guice which Provider<> we need as this class
       * may be instantiated outside the standard Guice Module set-up (e.g.
       * initial Servlet login filter)
       */
      GsonProvider gsonProvider) {
    this.config = config;
    this.httpProvider = httpClientProvider;
    this.gson = gsonProvider.get();
  }

  private static SecureRandom newRandomGenerator() {
    try {
      return SecureRandom.getInstance("SHA1PRNG");
    } catch (NoSuchAlgorithmException e) {
      throw new IllegalArgumentException(
          "No SecureRandom available for GitHub authentication", e);
    }
  }

  public String getAuthorizationUrl(String scopesString, String state) {
    return config.gitHubOAuthUrl + "?client_id=" + config.gitHubClientId
        + getURLEncodedParameter("&scope=", scopesString)
        + getURLEncodedParameter("&redirect_uri=", config.oAuthFinalRedirectUrl)
        + getURLEncodedParameter("&state=", state);
  }

  public String loginPhase1(HttpServletRequest request,
      HttpServletResponse response, Set<Scope> scopes) throws IOException {
    String scopesString = getScope(scopes);
    log.debug("Initiating GitHub Login for ClientId=" + config.gitHubClientId
        + " Scopes=" + scopesString);
    String state = newRandomState(request.getRequestURI().toString());
    log.debug("Initiating GitHub Login for ClientId=" + config.gitHubClientId + " Scopes=" + scopesString);
    response.sendRedirect(getAuthorizationUrl(scopesString, state));
    return state;
  }

  public String getScope(Set<Scope> scopes) {
    if(scopes.size() <= 0) {
      return "";
    }

    StringBuilder out = new StringBuilder();
    for (Scope scope : scopes) {
      if (out.length() > 0) {
        out.append(",");
      }
      out.append(scope.getValue());
    }
    return out.toString();
  }

  public static boolean isOAuthFinal(HttpServletRequest request) {
    return Strings.emptyToNull(request.getParameter("code")) != null
        && request.getParameter(FINAL_URL_PARAM) == null;
  }

  public static boolean isOAuthFinalForOthers(HttpServletRequest request) {
    String targetUrl = getTargetUrl(request);
    if (targetUrl.equals(request.getRequestURI())) {
      return false;
    }

    return Strings.emptyToNull(request.getParameter("code")) != null
        && request.getParameter(FINAL_URL_PARAM) == null;
  }

  public String newRandomState(String redirectUrl) {
    byte[] stateBin = new byte[20]; // SHA-1 size
    randomState.nextBytes(stateBin);
    return BaseEncoding.base64Url().encode(stateBin) + ME_SEPARATOR + redirectUrl;
  }

  public static boolean isOAuthLogin(HttpServletRequest request) {
    String requestUri = request.getRequestURI();
    return requestUri.indexOf(GitHubOAuthConfig.GERRIT_LOGIN) >= 0
        && request.getParameter(FINAL_URL_PARAM) == null;
  }

  public static boolean isOAuthLogout(HttpServletRequest request) {
    return request.getRequestURI().indexOf(GitHubOAuthConfig.GERRIT_LOGOUT) >= 0;
  }

  public static boolean isOAuthRequest(HttpServletRequest httpRequest) {
    return OAuthProtocol.isOAuthLogin(httpRequest) || OAuthProtocol.isOAuthFinal(httpRequest);
  }

  public AccessToken loginPhase2(HttpServletRequest request,
      HttpServletResponse response, String state) throws IOException {
    String requestState = request.getParameter("state");
    if (!Objects.equals(state, requestState)) {
      throw new IOException("Invalid authentication state: expected '" + state
          + "' but was '" + requestState + "'");
    }

    return getAccessToken(new OAuthVerifier(request.getParameter("code")));
  }

  public AccessToken getAccessToken(OAuthVerifier code) throws IOException {
    HttpPost post = new HttpPost(config.gitHubOAuthAccessTokenUrl);
    post.setHeader("Accept", "application/json");
    List<NameValuePair> nvps = new ArrayList<NameValuePair>();
    nvps.add(new BasicNameValuePair("client_id", config.gitHubClientId));
    nvps.add(new BasicNameValuePair("client_secret", config.gitHubClientSecret));
    nvps.add(new BasicNameValuePair("code", code.getValue()));
    post.setEntity(new UrlEncodedFormEntity(nvps, Charsets.UTF_8));

    HttpResponse postResponse = httpProvider.get().execute(post);
    if (postResponse.getStatusLine().getStatusCode() != HttpURLConnection.HTTP_OK) {
      log.error("POST " + config.gitHubOAuthAccessTokenUrl
          + " request for access token failed with status "
          + postResponse.getStatusLine());
      EntityUtils.consume(postResponse.getEntity());
      throw new IOException("GitHub OAuth request failed");
    }

    InputStream content = postResponse.getEntity().getContent();
    String tokenJsonString =
        CharStreams.toString(new InputStreamReader(content,
            StandardCharsets.UTF_8));
    AccessToken token = gson.fromJson(tokenJsonString, AccessToken.class);
    if (token.isError()) {
      log.error("POST " + config.gitHubOAuthAccessTokenUrl
          + " returned an error token: " + token);
      throw new IOException("Invalid GitHub OAuth token");
    }

    return token;
  }

  private static String getURLEncodedParameter(String prefix, String url) {
    try {
      return Strings.isNullOrEmpty(url) ? 
          "" : (prefix + URLEncoder.encode(url,"UTF-8"));
    } catch (UnsupportedEncodingException e) {
      throw new IllegalStateException("Cannot find UTF-8 encoding", e);
    }
  }

  public static String getTargetUrl(ServletRequest request) {
    int meEnd = state(request).indexOf(ME_SEPARATOR);
    String finalUrlSuffix = "?" + FINAL_URL_PARAM + "=true";
    if (meEnd > 0) {
      return state(request).substring(meEnd + 1) + finalUrlSuffix;
    } else {
      return finalUrlSuffix;
    }
  }

  private static String state(ServletRequest request) {
    return Strings.nullToEmpty(request.getParameter("state"));
  }

  public static String getTargetOAuthFinal(HttpServletRequest httpRequest) {
    String targetUrl = getTargetUrl(httpRequest);
    String code = getURLEncodedParameter("code=", httpRequest.getParameter("code"));
    String state = getURLEncodedParameter("&state=", httpRequest.getParameter("state"));
    return targetUrl + (targetUrl.indexOf('?') < 0 ? '?' : '&') + code + state;
  }

  @Override
  public String toString() {
    return "OAuthProtocol";
  }

}
