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.gerrit.extensions.auth.oauth.OAuthToken;
import com.google.gerrit.extensions.auth.oauth.OAuthVerifier;
import com.google.gson.Gson;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
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 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;

@Singleton
public class OAuthProtocol {
  /**
   * Supported OAuth Scopes.
   *
   * <p>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
            + "]";
      }
      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) {
      if (obj == null) {
        return false;
      }
      if (getClass() != obj.getClass()) {
        return false;
      }
      final AccessToken other = (AccessToken) obj;
      return Objects.equals(this.accessToken, other.accessToken)
          && Objects.equals(this.raw, other.raw)
          && Objects.equals(this.tokenType, other.tokenType);
    }

    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<>();
    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;
    }
    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";
  }
}
