# Copyright 2015 Google Inc.
#
# 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.

"""Application default credentials.

Implements application default credentials and project ID detection.
"""

import io
import json
import logging
import os

from google.auth import environment_vars
from google.auth import exceptions
import google.auth.transport._http_client

_LOGGER = logging.getLogger(__name__)

# Valid types accepted for file-based credentials.
_AUTHORIZED_USER_TYPE = 'authorized_user'
_SERVICE_ACCOUNT_TYPE = 'service_account'
_VALID_TYPES = (_AUTHORIZED_USER_TYPE, _SERVICE_ACCOUNT_TYPE)

# Help message when no credentials can be found.
_HELP_MESSAGE = """
Could not automatically determine credentials. Please set {env} or
explicitly create credential and re-run the application. For more
information, please see
https://developers.google.com/accounts/docs/application-default-credentials.
""".format(env=environment_vars.CREDENTIALS).strip()


def _load_credentials_from_file(filename):
    """Loads credentials from a file.

    The credentials file must be a service account key or stored authorized
    user credentials.

    Args:
        filename (str): The full path to the credentials file.

    Returns:
        Tuple[google.auth.credentials.Credentials, Optional[str]]: Loaded
            credentials and the project ID. Authorized user credentials do not
            have the project ID information.

    Raises:
        google.auth.exceptions.DefaultCredentialsError: if the file is in the
            wrong format.
    """
    with io.open(filename, 'r') as file_obj:
        try:
            info = json.load(file_obj)
        except ValueError as exc:
            raise exceptions.DefaultCredentialsError(
                'File {} is not a valid json file.'.format(filename), exc)

    # The type key should indicate that the file is either a service account
    # credentials file or an authorized user credentials file.
    credential_type = info.get('type')

    if credential_type == _AUTHORIZED_USER_TYPE:
        from google.auth import _cloud_sdk

        try:
            credentials = _cloud_sdk.load_authorized_user_credentials(info)
        except ValueError as exc:
            raise exceptions.DefaultCredentialsError(
                'Failed to load authorized user credentials from {}'.format(
                    filename), exc)
        # Authorized user credentials do not contain the project ID.
        return credentials, None

    elif credential_type == _SERVICE_ACCOUNT_TYPE:
        from google.oauth2 import service_account

        try:
            credentials = (
                service_account.Credentials.from_service_account_info(info))
        except ValueError as exc:
            raise exceptions.DefaultCredentialsError(
                'Failed to load service account credentials from {}'.format(
                    filename), exc)
        return credentials, info.get('project_id')

    else:
        raise exceptions.DefaultCredentialsError(
            'The file {file} does not have a valid type. '
            'Type is {type}, expected one of {valid_types}.'.format(
                file=filename, type=credential_type, valid_types=_VALID_TYPES))


def _get_gcloud_sdk_credentials():
    """Gets the credentials and project ID from the Cloud SDK."""
    from google.auth import _cloud_sdk

    # Check if application default credentials exist.
    credentials_filename = (
        _cloud_sdk.get_application_default_credentials_path())

    if not os.path.isfile(credentials_filename):
        return None, None

    credentials, project_id = _load_credentials_from_file(
        credentials_filename)

    if not project_id:
        project_id = _cloud_sdk.get_project_id()

    if not project_id:
        _LOGGER.warning(
            'No project ID could be determined from the Cloud SDK '
            'configuration. Consider running `gcloud config set project` or '
            'setting the %s environment variable', environment_vars.PROJECT)

    return credentials, project_id


def _get_explicit_environ_credentials():
    """Gets credentials from the GOOGLE_APPLICATION_CREDENTIALS environment
    variable."""
    explicit_file = os.environ.get(environment_vars.CREDENTIALS)

    if explicit_file is not None:
        credentials, project_id = _load_credentials_from_file(
            os.environ[environment_vars.CREDENTIALS])

        if not project_id:
            _LOGGER.warning(
                'No project ID could be determined from the credentials at %s '
                'Consider setting the %s environment variable',
                environment_vars.CREDENTIALS, environment_vars.PROJECT)

        return credentials, project_id

    else:
        return None, None


def _get_gae_credentials():
    """Gets Google App Engine App Identity credentials and project ID."""
    from google.auth import app_engine

    try:
        credentials = app_engine.Credentials()
        project_id = app_engine.get_project_id()
        return credentials, project_id
    except EnvironmentError:
        return None, None


def _get_gce_credentials(request=None):
    """Gets credentials and project ID from the GCE Metadata Service."""
    # Ping requires a transport, but we want application default credentials
    # to require no arguments. So, we'll use the _http_client transport which
    # uses http.client. This is only acceptable because the metadata server
    # doesn't do SSL and never requires proxies.
    from google.auth import compute_engine
    from google.auth.compute_engine import _metadata

    if request is None:
        request = google.auth.transport._http_client.Request()

    if _metadata.ping(request=request):
        # Get the project ID.
        try:
            project_id = _metadata.get_project_id(request=request)
        except exceptions.TransportError:
            _LOGGER.warning(
                'No project ID could be determined from the Compute Engine '
                'metadata service. Consider setting the %s environment '
                'variable.', environment_vars.PROJECT)
            project_id = None

        return compute_engine.Credentials(), project_id
    else:
        return None, None


def default(scopes=None, request=None):
    """Gets the default credentials for the current environment.

    `Application Default Credentials`_ provides an easy way to obtain
    credentials to call Google APIs for server-to-server or local applications.
    This function acquires credentials from the environment in the following
    order:

    1. If the environment variable ``GOOGLE_APPLICATION_CREDENTIALS`` is set
       to the path of a valid service account JSON private key file, then it is
       loaded and returned. The project ID returned is the project ID defined
       in the service account file if available (some older files do not
       contain project ID information).
    2. If the `Google Cloud SDK`_ is installed and has application default
       credentials set they are loaded and returned.

       To enable application default credentials with the Cloud SDK run::

            gcloud auth application-default login

       If the Cloud SDK has an active project, the project ID is returned. The
       active project can be set using::

            gcloud config set project

    3. If the application is running in the `App Engine standard environment`_
       then the credentials and project ID from the `App Identity Service`_
       are used.
    4. If the application is running in `Compute Engine`_ or the
       `App Engine flexible environment`_ then the credentials and project ID
       are obtained from the `Metadata Service`_.
    5. If no credentials are found,
       :class:`~google.auth.exceptions.DefaultCredentialsError` will be raised.

    .. _Application Default Credentials: https://developers.google.com\
            /identity/protocols/application-default-credentials
    .. _Google Cloud SDK: https://cloud.google.com/sdk
    .. _App Engine standard environment: https://cloud.google.com/appengine
    .. _App Identity Service: https://cloud.google.com/appengine/docs/python\
            /appidentity/
    .. _Compute Engine: https://cloud.google.com/compute
    .. _App Engine flexible environment: https://cloud.google.com\
            /appengine/flexible
    .. _Metadata Service: https://cloud.google.com/compute/docs\
            /storing-retrieving-metadata

    Example::

        import google.auth

        credentials, project_id = google.auth.default()

    Args:
        scopes (Sequence[str]): The list of scopes for the credentials. If
            specified, the credentials will automatically be scoped if
            necessary.
        request (google.auth.transport.Request): An object used to make
            HTTP requests. This is used to detect whether the application
            is running on Compute Engine. If not specified, then it will
            use the standard library http client to make requests.

    Returns:
        Tuple[~google.auth.credentials.Credentials, Optional[str]]:
            the current environment's credentials and project ID. Project ID
            may be None, which indicates that the Project ID could not be
            ascertained from the environment.

    Raises:
        ~google.auth.exceptions.DefaultCredentialsError:
            If no credentials were found, or if the credentials found were
            invalid.
    """
    from google.auth.credentials import with_scopes_if_required

    explicit_project_id = os.environ.get(
        environment_vars.PROJECT,
        os.environ.get(environment_vars.LEGACY_PROJECT))

    checkers = (
        _get_explicit_environ_credentials,
        _get_gcloud_sdk_credentials,
        _get_gae_credentials,
        lambda: _get_gce_credentials(request))

    for checker in checkers:
        credentials, project_id = checker()
        if credentials is not None:
            credentials = with_scopes_if_required(credentials, scopes)
            return credentials, explicit_project_id or project_id

    raise exceptions.DefaultCredentialsError(_HELP_MESSAGE)
