# Copyright 2016 Google Inc. All Rights Reserved.
#
# 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.

"""Helpers for authentication using oauth2client or google-auth."""

import httplib2

try:
    import google.auth
    import google.auth.credentials

    HAS_GOOGLE_AUTH = True
except ImportError:  # pragma: NO COVER
    HAS_GOOGLE_AUTH = False

try:
    import google_auth_httplib2
except ImportError:  # pragma: NO COVER
    google_auth_httplib2 = None

try:
    import oauth2client
    import oauth2client.client

    HAS_OAUTH2CLIENT = True
except ImportError:  # pragma: NO COVER
    HAS_OAUTH2CLIENT = False


def credentials_from_file(filename, scopes=None, quota_project_id=None):
    """Returns credentials loaded from a file."""
    if HAS_GOOGLE_AUTH:
        credentials, _ = google.auth.load_credentials_from_file(filename, scopes=scopes, quota_project_id=quota_project_id)
        return credentials
    else:
        raise EnvironmentError(
        "client_options.credentials_file is only supported in google-auth.")


def default_credentials(scopes=None, quota_project_id=None):
    """Returns Application Default Credentials."""
    if HAS_GOOGLE_AUTH:
        credentials, _ = google.auth.default(scopes=scopes, quota_project_id=quota_project_id)
        return credentials
    elif HAS_OAUTH2CLIENT:
        if scopes is not None or quota_project_id is not None:
            raise EnvironmentError(
                "client_options.scopes and client_options.quota_project_id are not supported in oauth2client."
                "Please install google-auth."
            )
        return oauth2client.client.GoogleCredentials.get_application_default()
    else:
        raise EnvironmentError(
            "No authentication library is available. Please install either "
            "google-auth or oauth2client."
        )


def with_scopes(credentials, scopes):
    """Scopes the credentials if necessary.

    Args:
        credentials (Union[
            google.auth.credentials.Credentials,
            oauth2client.client.Credentials]): The credentials to scope.
        scopes (Sequence[str]): The list of scopes.

    Returns:
        Union[google.auth.credentials.Credentials,
            oauth2client.client.Credentials]: The scoped credentials.
    """
    if HAS_GOOGLE_AUTH and isinstance(credentials, google.auth.credentials.Credentials):
        return google.auth.credentials.with_scopes_if_required(credentials, scopes)
    else:
        try:
            if credentials.create_scoped_required():
                return credentials.create_scoped(scopes)
            else:
                return credentials
        except AttributeError:
            return credentials


def authorized_http(credentials):
    """Returns an http client that is authorized with the given credentials.

    Args:
        credentials (Union[
            google.auth.credentials.Credentials,
            oauth2client.client.Credentials]): The credentials to use.

    Returns:
        Union[httplib2.Http, google_auth_httplib2.AuthorizedHttp]: An
            authorized http client.
    """
    from googleapiclient.http import build_http

    if HAS_GOOGLE_AUTH and isinstance(credentials, google.auth.credentials.Credentials):
        if google_auth_httplib2 is None:
            raise ValueError(
                "Credentials from google.auth specified, but "
                "google-api-python-client is unable to use these credentials "
                "unless google-auth-httplib2 is installed. Please install "
                "google-auth-httplib2."
            )
        return google_auth_httplib2.AuthorizedHttp(credentials, http=build_http())
    else:
        return credentials.authorize(build_http())


def refresh_credentials(credentials):
    # Refresh must use a new http instance, as the one associated with the
    # credentials could be a AuthorizedHttp or an oauth2client-decorated
    # Http instance which would cause a weird recursive loop of refreshing
    # and likely tear a hole in spacetime.
    refresh_http = httplib2.Http()
    if HAS_GOOGLE_AUTH and isinstance(credentials, google.auth.credentials.Credentials):
        request = google_auth_httplib2.Request(refresh_http)
        return credentials.refresh(request)
    else:
        return credentials.refresh(refresh_http)


def apply_credentials(credentials, headers):
    # oauth2client and google-auth have the same interface for this.
    if not is_valid(credentials):
        refresh_credentials(credentials)
    return credentials.apply(headers)


def is_valid(credentials):
    if HAS_GOOGLE_AUTH and isinstance(credentials, google.auth.credentials.Credentials):
        return credentials.valid
    else:
        return (
            credentials.access_token is not None
            and not credentials.access_token_expired
        )


def get_credentials_from_http(http):
    if http is None:
        return None
    elif hasattr(http.request, "credentials"):
        return http.request.credentials
    elif hasattr(http, "credentials") and not isinstance(
        http.credentials, httplib2.Credentials
    ):
        return http.credentials
    else:
        return None
