# 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 default_credentials():
    """Returns Application Default Credentials."""
    if HAS_GOOGLE_AUTH:
        credentials, _ = google.auth.default()
        return credentials
    elif HAS_OAUTH2CLIENT:
        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
