# Copyright 2016 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""API for interacting with the buildbucket service directly.

Instead of triggering jobs by emitting annotations then handled by the master,
this module allows slaves to directly post requests to buildbucket.
"""

import json

from recipe_engine import recipe_api


class BuildbucketApi(recipe_api.RecipeApi):
  """A module for interacting with buildbucket."""

  def __init__(self, buildername, buildnumber, *args, **kwargs):
    super(BuildbucketApi, self).__init__(*args, **kwargs)
    self._buildername = buildername
    self._buildnumber = buildnumber
    self._properties = None

  def get_config_defaults(self):
    if self.m.platform.is_win:
      return {'PLATFORM': 'win'}
    return {'PLATFORM': 'default'}

  def _configure_defaults(self):
    """Apply default configuration if no configuration has been set.

    Ideally whoever uses this api will explicitly set the configuration by
    doing `api.buildbucket.set_config('production_buildbucket')`, but to make
    this module usable even in case they don't configure it, we set the default
    to the production instance of buildbucket."""
    # There's only two items in this module's configuration, the path to the
    # buildbucket cli client binary and the buildbucket hostname, this default
    # configuration will override them.
    if not self.c or not self.c.complete():
      self.set_config('production_buildbucket')

  def _tags_for_build(self, bucket, parameters, override_tags=None):
    buildbucket_info = self.properties or {}
    original_tags_list = buildbucket_info.get('build', {}).get('tags', [])

    original_tags = dict(t.split(':', 1) for t in original_tags_list)
    new_tags = {'user_agent': 'recipe'}

    if 'buildset' in original_tags:
      new_tags['buildset'] = original_tags['buildset']
    builder_name = parameters.get('builder_name')
    if builder_name:
      new_tags['builder'] = builder_name
    if bucket.startswith('master.'):
      new_tags['master'] = bucket[7:]
    if self._buildnumber is not None:
      new_tags['parent_buildnumber'] = str(self._buildnumber)
    if self._buildername is not None:
      new_tags['parent_buildername'] = str(self._buildername)

    new_tags.update(override_tags or {})
    return sorted([':'.join((x, y)) for x, y in new_tags.iteritems()])

  @property
  def properties(self):
    """Returns (dict-like or None): The BuildBucket properties, if present."""
    if self._properties is None:
      # Not cached, load and deserialize from properties.
      props = self.m.properties.get('buildbucket')
      if props is not None:
        if isinstance(props, basestring):
          props = json.loads(props)
        self._properties = props
    return self._properties

  def put(self, builds, service_account=None, **kwargs):
    """Puts a batch of builds.

    Args:
      builds (list): A list of dicts, where keys are:
        'bucket': (required) name of the bucket for the request.
        'parameters' (dict): (required) arbitrary json-able parameters that a
          build system would be able to interpret.
        'tags': (optional) a dict(str->str) of tags for the build. These will
          be added to those generated by this method and override them if
          appropriate.
      service_account (str): (optional) path to locally saved secrets for
        service account to authenticate as.

    Returns:
      A step that as its .stdout property contains the response object as
      returned by buildbucket.
    """
    build_specs = []
    for build in builds:
      build_specs.append(json.dumps({
        'bucket': build['bucket'],
        'parameters_json': json.dumps(build['parameters'], sort_keys=True),
        'tags': self._tags_for_build(build['bucket'], build['parameters'],
                                     build.get('tags')),
      }, sort_keys=True))
    return self._call_service('put', build_specs, service_account, **kwargs)

  def cancel_build(self, build_id, service_account=None, **kwargs):
    return self._call_service('cancel', [build_id], service_account, **kwargs)

  def get_build(self, build_id, service_account=None, **kwargs):
    return self._call_service('get', [build_id], service_account, **kwargs)

  def _call_service(self, command, args, service_account=None, **kwargs):
    # TODO: Deploy buildbucket client using cipd.
    self._configure_defaults()
    step_name = kwargs.pop('name', 'buildbucket.' + command)
    if service_account:
      args = ['--service-account-json', service_account] + args
    args = [str(self.c.buildbucket_client_path), command, '--host',
            self.c.buildbucket_host] + args
    return self.m.step(
        step_name, args, stdout=self.m.json.output(), **kwargs)
