# Copyright 2016 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.

"""Code releated to buildbucket.

Buildbucket is a generic build queue. A build requester can schedule
a build and wait for a result. A building system, such as Buildbot,
can lease it, build it and report a result back.

For more documents about buildbucket, please refer to:
'https://chromium.googlesource.com/infra/infra/+/master/appengine/
cr-buildbucket/README.md'
"""

from __future__ import print_function

import json
import os

from chromite.cbuildbot import topology
from chromite.lib import auth
from chromite.lib import cros_logging as logging
from chromite.lib import retry_util

# from third_party
import httplib2

# Methods
PUT_METHOD = 'PUT'
POST_METHOD = 'POST'
GET_METHOD = 'GET'

# Statuses
STARTED_STATUS = 'STARTED'
SCHEDULED_STATUS = 'SCHEDULED'
COMPLETED_STATUS = 'COMPLETED'

def GetServiceAccount(service_account=None):
  """Get service account file.

  Args:
    service_account: service account file path.

  Returns:
    Return service_account path if the file exists; else, return None.
  """
  if service_account and os.path.isfile(service_account):
    logging.info('Get service account %s', service_account)
    return service_account
  return None

def BuildBucketAuth(service_account=None):
  """Build buildbucket http auth.

  Args:
    service_account: service account file path.

  Returns:
    Http instance with 'Authorization' inforamtion.
  """
  return auth.Authorize(auth.GetAccessToken,
                        httplib2.Http(),
                        service_account_json=service_account)

def GetHost(testjob):
  """Get buildbucket Server host."""
  host = topology.topology[
      topology.BUILDBUCKET_TEST_HOST_KEY if testjob
      else topology.BUILDBUCKET_HOST_KEY]

  return host

def BuildBucketRequest(http, url, method, body, dryrun):
  """Generic buildbucket request.

  Args:
    http: Http instance.
    url: Buildbucket url to send requests.
    method: Request method.
    body: Body of http request (string object).
    dryrun: Whether a dryrun.

  Returns:
    Content if request succeeds.
  """
  if dryrun:
    logging.info('Dryrun mode is on; Would have made a request '
                 'with url %s method %s body:\n%s', url, method, body)
    return

  def try_method():
    response, content = http.request(
        url,
        method,
        body=body,
        headers={'Content-Type': 'application/json'},
    )

    if int(response['status']) // 100 != 2:
      raise Exception('Got a %s response from buildbucket '
                      'with url: %s\ncontent: %s'
                      % (response['status'], url, content))

    # Return content_dict
    return json.loads(content)

  return retry_util.GenericRetry(lambda _: True, 3, try_method)

def PutBuildBucket(body, http, testjob, dryrun):
  """Send Put request to buildbucket server.

  Args:
    body: Body of http request.
    http: Http instance.
    testjob: Whether to use the test instance of the buildbucket server.
    dryrun: Whether a dryrun.

  Returns:
    Content if request succeeds.
  """
  url = 'https://%(hostname)s/_ah/api/buildbucket/v1/builds' % {
      'hostname': GetHost(testjob)
  }

  return BuildBucketRequest(http, url, PUT_METHOD, body, dryrun)

def GetBuildBucket(buildbucket_id, http, testjob, dryrun):
  """Send Get request to buildbucket server.

  Args:
    buildbucket_id: Build to get status.
    http: Http instance.
    testjob: Whether to use the test instance of the buildbucket server.
    dryrun: Whether a dryrun.

  Returns:
    Content if request succeeds.
  """
  url = 'https://%(hostname)s/_ah/api/buildbucket/v1/builds/%(id)s' % {
      'hostname': GetHost(testjob),
      'id': buildbucket_id
  }

  return BuildBucketRequest(http, url, GET_METHOD, None, dryrun)

def CancelBuildBucket(buildbucket_id, http, testjob, dryrun):
  """Send Cancel request to buildbucket server.

  Args:
    buildbucket_id: build to cancel.
    http: Http instance.
    testjob: Whether to use the test instance of the buildbucket server.
    dryrun: Whether a dryrun.

  Returns:
    Content if request succeeds.
  """
  url = 'https://%(hostname)s/_ah/api/buildbucket/v1/builds/%(id)s/cancel' % {
      'hostname': GetHost(testjob),
      'id': buildbucket_id
  }

  return BuildBucketRequest(http, url, POST_METHOD, '{}', dryrun)

def CancelBatchBuildBucket(buildbucket_ids, http, testjob, dryrun):
  """Send CancelBatch request to buildbucket server.

  Args:
    buildbucket_ids: builds to cancel.
    http: Http instance.
    testjob: Whether to use the test instance of the buildbucket server.
    dryrun: Whether a dryrun.

  Returns:
    Content if request succeeds.
  """
  url = 'https://%(hostname)s/_ah/api/buildbucket/v1/builds/cancel' % {
      'hostname': GetHost(testjob)
  }

  body = json.dumps({'build_ids': buildbucket_ids})

  return BuildBucketRequest(http, url, POST_METHOD, body, dryrun)

def HasError(content):
  return content and content.get('error')

def GetErrorReason(content):
  return (content.get('error').get('reason')
          if HasError(content) else None)

def HasBuild(content):
  return content and content.get('build')

def GetBuildId(content):
  return (content.get('build').get('id')
          if HasBuild(content) else None)

def GetBuildStatus(content):
  return (content.get('build').get('status')
          if HasBuild(content) else None)

def GetBuildResult(content):
  return (content.get('build').get('result')
          if HasBuild(content) else None)

def GetResultMap(content):
  """Get a build_id to result map."""
  if content is None or content.get('results') is None:
    return

  build_result_map = {}
  for r in content.get('results'):
    if r.get('build_id') is not None:
      build_id = r.pop('build_id')
      build_result_map[build_id] = r

  return build_result_map
