# -*- coding: utf-8 -*-
# Copyright 2015 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Functions for authenticating httplib2 requests with OAuth2 tokens."""

from __future__ import print_function

import os
import sys

import httplib2

from chromite.lib import cipd
from chromite.lib import cros_build_lib
from chromite.lib import cros_logging as logging
from chromite.lib import retry_util
from chromite.lib import path_util


assert sys.version_info >= (3, 6), 'This module requires Python 3.6+'


REFRESH_STATUS_CODES = [401]

# Retry times on get_access_token
RETRY_GET_ACCESS_TOKEN = 3


class AccessTokenError(Exception):
  """Error accessing the token."""


def _GetCipdBinary(pkg_name, bin_name, instance_id):
  """Returns a local path to the given binary fetched from cipd."""
  cache_dir = os.path.join(path_util.GetCacheDir(), 'cipd', 'packages')
  path = cipd.InstallPackage(
      cipd.GetCIPDFromCache(),
      pkg_name,
      instance_id,
      destination=cache_dir)

  return os.path.join(path, bin_name)


# crbug:871831 default to last sha1 version.
def GetLuciAuth(
    instance_id='git_revision:fd059ace316e4dbcaa5afdcec9ed4a855c4f3c65'):
  """Returns a path to the luci-auth binary.

  This will download and install the luci-auth package if it is not already
  deployed.

  Args:
    instance_id: The instance-id of the package to install.

  Returns:
    the path to the luci-auth binary.
  """
  return _GetCipdBinary(
      'infra/tools/luci-auth/linux-amd64',
      'luci-auth',
      instance_id)


# crbug:871831 default to last sha1 version.
def GetLuciGitCreds(
    instance_id='git_revision:fd059ace316e4dbcaa5afdcec9ed4a855c4f3c65'):
  """Returns a path to the git-credential-luci binary.

  This will download and install the git-credential-luci package if it is not
  already deployed.

  Args:
    instance_id: The instance-id of the package to install.

  Returns:
    the path to the git-credential-luci binary.
  """
  return _GetCipdBinary(
      'infra/tools/luci/git-credential-luci/linux-amd64',
      'git-credential-luci',
      instance_id)


def Login(service_account_json=None):
  """Logs a user into chrome-infra-auth using luci-auth.

  Runs 'luci-auth login' to get a OAuth2 refresh token.

  Args:
    service_account_json: A optional path to a service account.

  Raises:
    AccessTokenError if login command failed.
  """
  logging.info('Logging into chrome-infra-auth with service_account %s',
               service_account_json)

  cmd = [GetLuciAuth(), 'login']
  if service_account_json and os.path.isfile(service_account_json):
    cmd += ['-service-account-json=%s' % service_account_json]

  result = cros_build_lib.run(
      cmd,
      print_cmd=True,
      check=False)

  if result.returncode:
    raise AccessTokenError('Failed at  logging in to chrome-infra-auth: %s,'
                           ' may retry.')


def Token(service_account_json=None):
  """Get the token using luci-auth.

  Runs 'luci-auth token' to get the OAuth2 token.

  Args:
    service_account_json: A optional path to a service account.

  Returns:
    The token string if the command succeeded;

  Raises:
    AccessTokenError if token command failed.
  """
  cmd = [GetLuciAuth(), 'token']
  if service_account_json and os.path.isfile(service_account_json):
    cmd += ['-service-account-json=%s' % service_account_json]

  result = cros_build_lib.run(
      cmd,
      print_cmd=False,
      capture_output=True,
      check=False,
      encoding='utf-8')

  if result.returncode:
    raise AccessTokenError('Failed at getting the access token, may retry.')

  return result.output.strip()


def _TokenAndLoginIfNeed(service_account_json=None, force_token_renew=False):
  """Run Token and Login opertions.

  If force_token_renew is on, run Login operation first to force token renew,
  then run Token operation to return token string.
  If force_token_renew is off, run Token operation first. If no token found,
  run Login operation to refresh the token. Throw an AccessTokenError after
  running the Login operation, so that GetAccessToken can retry on
  _TokenAndLoginIfNeed.

  Args:
    service_account_json: A optional path to a service account.
    force_token_renew: Boolean indicating whether to force login to renew token
      before returning a token. Default to False.

  Returns:
    The token string if the command succeeded; else, None.

  Raises:
    AccessTokenError if the Token operation failed.
  """
  if force_token_renew:
    Login(service_account_json=service_account_json)
    return Token(service_account_json=service_account_json)
  else:
    try:
      return Token(service_account_json=service_account_json)
    except AccessTokenError as e:
      Login(service_account_json=service_account_json)
      # Raise the error and let the caller decide wether to retry
      raise e


def GetAccessToken(**kwargs):
  """Returns an OAuth2 access token using luci-auth.

  Retry the _TokenAndLoginIfNeed function when the error thrown is an
  AccessTokenError.

  Args:
    kwargs: A list of keyword arguments to pass to _TokenAndLoginIfNeed.

  Returns:
    The access token string or None if failed to get access token.
  """
  service_account_json = kwargs.get('service_account_json')
  force_token_renew = kwargs.get('force_token_renew', False)
  retry = lambda e: isinstance(e, AccessTokenError)
  try:
    result = retry_util.GenericRetry(
        retry, RETRY_GET_ACCESS_TOKEN,
        _TokenAndLoginIfNeed,
        service_account_json=service_account_json,
        force_token_renew=force_token_renew,
        sleep=3)
    return result
  except AccessTokenError as e:
    logging.error('Failed at getting the access token: %s ', e)
    # Do not raise the AccessTokenError here.
    # Let the response returned by the request handler
    # tell the status and errors.
    return


def GitCreds(service_account_json=None):
  """Get the git credential using git-credential-luci.

  Args:
    service_account_json: A optional path to a service account.

  Returns:
    The git credential if the command succeeded;

  Raises:
    AccessTokenError if token command failed.
  """
  cmd = [GetLuciGitCreds(), 'get']
  if service_account_json and os.path.isfile(service_account_json):
    cmd += ['-service-account-json=%s' % service_account_json]

  result = cros_build_lib.run(
      cmd,
      print_cmd=False,
      capture_output=True,
      check=False,
      encoding='utf-8')

  if result.returncode:
    raise AccessTokenError('Unable to fetch git credential.')

  for line in result.stdout.splitlines():
    if line.startswith('password='):
      return line.split('password=')[1].strip()

  raise AccessTokenError('Unable to fetch git credential.')


class AuthorizedHttp(object):
  """Authorized http instance"""

  def __init__(self, get_access_token, http, **kwargs):
    self.get_access_token = get_access_token
    self.http = http if http is not None else httplib2.Http()
    self.token = self.get_access_token(**kwargs)
    self.kwargs = kwargs

  # Adapted from oauth2client.OAuth2Credentials.authorize.
  # We can't use oauthclient2 because the import will fail on slaves due to
  # missing PyOpenSSL (crbug.com/498467).
  def request(self, *args, **kwargs):
    headers = kwargs.get('headers', {}).copy()
    headers['Authorization'] = 'Bearer %s' % self.token
    kwargs['headers'] = headers

    resp, content = self.http.request(*args, **kwargs)
    if resp.status in REFRESH_STATUS_CODES:
      logging.info('OAuth token TTL expired, auto-refreshing')

      # Token expired, force token renew
      kwargs_copy = dict(self.kwargs, force_token_renew=True)
      self.token = self.get_access_token(**kwargs_copy)

      # TODO(phobbs): delete the "access_token" key from the token file used.
      headers['Authorization'] = 'Bearer %s' % self.token
      resp, content = self.http.request(*args, **kwargs)

    return resp, content
