# Copyright 2019 The LUCI Authors. All rights reserved.
# Use of this source code is governed under the Apache License, Version 2.0
# that can be found in the LICENSE file.

"""Defines classes which the `step` module uses to describe steps-to-run to the
RecipeEngine.

# TODO(iannucci): Simplify this.
"""

import pprint

import attr

from .attr_util import attr_type, attr_dict_type, attr_seq_type, attr_value_is

from ..types import FrozenDict, freeze, thaw
from ..util import InputPlaceholder, OutputPlaceholder, Placeholder, sentinel


@attr.s(frozen=True)
class EnvAffix(object):
  """Expresses a mapping of environment keys to a list of paths.

  This is used as StepConfig's "env_prefixes" and "env_suffixes" value.
  """
  mapping = attr.ib(factory=dict,
                    validator=attr_dict_type(str, str, value_seq=True))
  pathsep = attr.ib(default=None, validator=attr_type((str, type(None))))

  def __attrs_post_init__(self):
    object.__setattr__(self, 'mapping', freeze(self.mapping))

  def render_step_value(self):
    rendered = {k: (self.pathsep or ':').join(str(x) for x in v)
                for k, v in self.mapping.iteritems()}
    return pprint.pformat(rendered, width=1024)


@attr.s(frozen=True)
class TriggerSpec(object):
  """TriggerSpec is the internal representation of a raw trigger step. You should
  use the standard 'step' recipe module, which will construct trigger specs
  via API.
  """
  # The name of the builder to trigger.
  builder_name = attr.ib(validator=attr_type(str))

  # The name of the trigger bucket.
  bucket = attr.ib(default='', validator=attr_type(str))

  # Key/value properties dictionary.
  properties = attr.ib(factory=dict, validator=attr_type((dict, FrozenDict)))

  # Optional list of BuildBot change dicts.
  buildbot_changes = attr.ib(default=(), validator=attr_seq_type(dict))

  # Optional list of tag strings.
  tags = attr.ib(default=(), validator=attr_seq_type(str))

  # If true and triggering fails asynchronously, fail the entire build.
  critical = attr.ib(default=True, validator=attr_type(bool))

  def _asdict(self):
    d = dict((k, v) for k, v in attr.asdict(self).iteritems() if v)
    if d['critical']:
      d.pop('critical')
    return d


def _file_placeholder(base_placeholder_type):
  """Returns a attr validator for StepConfig.stdin/stdout/stderr."""
  return [
    attr_type((str, base_placeholder_type, type(None))),
    attr_value_is(
        'backed by a file',
        lambda value: (
          value is None or isinstance(value, str) or
          value.backing_file is not Placeholder.backing_file
        )
    )
  ]


@attr.s
class StepConfig(object):
  """StepConfig is the representation of a raw step as the recipe_engine sees it.
  You should use the standard 'step' recipe module, which will construct and
  pass this data to the engine for you, instead. The only reason why you would
  need to worry about this object is if you're modifying the step module
  itself.
  """
  # The list of name pieces for this step. Every piece indicates a level of
  # nesting. So, ('foo', 'bar') would be the step 'bar' nested under the parent
  # 'foo'.
  name_tokens = attr.ib(validator=attr_seq_type(basestring))

  # List of args of the command to run. Acceptable types: Placeholder or any
  # str()'able type.
  cmd = attr.ib(
      default=(),
      converter=(lambda value: [
        itm if isinstance(itm, Placeholder) else str(itm)
        for itm in value
      ]),
      validator=attr_seq_type((str, Placeholder)))

  # Absolute path to working directory for the command.
  cwd = attr.ib(
      default=None,
      validator=attr_type((str, type(None))))

  # Overrides for environment variables
  #
  # Each value is % formatted with the entire existing os.environ. A value of
  # `None` will remove that envvar from the environ. e.g.
  #
  #   {
  #      "envvar": "%(envvar)s-extra",
  #      "delete_this": None,
  #      "static_value": "something",
  #   }
  #
  # The "env_prefixes" parameter contain values that transform an environment
  # variable into a "pathsep"-delimited sequence of items:
  #   - If an environment variable is also specified for this key, it will be
  #     appended as the last element: <prefix0>:...:<prefixN>:ENV
  #   - If no environment variable is specified, the current environment's value
  #     will be appended, unless it's empty: <prefix0>:...:<prefixN>[:ENV]?
  #   - If an environment variable with a value of None (delete) is specified,
  #     nothing will be appeneded: <prefix0>:...:<prefixN>
  # "env_suffixes" is identical, except that it appends instead of prepends to
  # the envvar.
  #
  # NOTE: Always prefer env_prefixes and env_suffixes to manually substituting
  # variables with %(envvar)s.
  env = attr.ib(factory=dict, validator=attr_dict_type(str, (str, type(None))))
  env_prefixes = attr.ib(factory=EnvAffix, validator=attr_type(EnvAffix))
  env_suffixes = attr.ib(factory=EnvAffix, validator=attr_type(EnvAffix))

  # If True, lets the step emit its own @@@annotations@@@.
  #
  # TODO(iannucci): Move this into an annotee wrapper command in the `step`
  # module.
  #
  # NOTE: Enabling this can cause some buggy behavior. Use
  # step_result.presentation instead. If you have questions, please contact
  # infra-dev@chromium.org.
  allow_subannotations = attr.ib(default=False, validator=attr_type(bool))

  # The time, in seconds, that this step is allowed to run for before timing
  # out.
  timeout = attr.ib(
      default=None,
      validator=attr_type((int, float, long, type(None))))

  # Set of return codes allowed. If the step process returns something not on
  # this list, it will raise a StepFailure (or InfraFailure if infra_step is
  # True).
  #
  # Alternatively, the sentinel StepConfig.ALL_OK can be used to allow any
  # return code.
  ok_ret = attr.ib(default=(0,))
  @ok_ret.validator
  def _ok_ret_validator(self, attrib, value):
    if value is self.ALL_OK:
      return
    attr_seq_type((int, long))(self, attrib, value)

  # If True and the step returns an unacceptable return code (see `ok_ret`),
  # this will raise InfraFailure instead of StepFailure.
  infra_step = attr.ib(default=False, validator=attr_type(bool))

  # Standard handle redirection.
  # If None, stdin is closed and stdout/stderr are routed to the UI.
  # These placeholders require a non-default implementation of `backing_file`.
  stdin = attr.ib(default=None, validator=_file_placeholder(InputPlaceholder))
  stdout = attr.ib(default=None, validator=_file_placeholder(OutputPlaceholder))
  stderr = attr.ib(default=None, validator=_file_placeholder(OutputPlaceholder))

  # A function returning recipe_test_api.StepTestData.
  #
  # A factory which returns a StepTestData object that will be used as the
  # default test data for this step. The recipe author can override/augment this
  # object in the GenTests function.
  step_test_data = attr.ib(
      default=None,
      validator=attr_value_is(
          'None or callable',
          lambda value: value is None or callable(value)))

  # DEPRECATED: Do not use this.
  trigger_specs = attr.ib(default=(), validator=attr_seq_type(TriggerSpec))

  def __attrs_post_init__(self):
    object.__setattr__(self, 'name_tokens', tuple(self.name_tokens))
    object.__setattr__(self, 'cmd', tuple(self.cmd))
    object.__setattr__(self, 'trigger_specs', tuple(self.trigger_specs))

    # if cmd is empty, then remove all values except for the few that actually
    # apply with a null command.
    if not self.cmd:
      _keep_fields = ('name_tokens', 'cmd', 'trigger_specs')
      for attrib in attr.fields(self.__class__):
        if attrib.name in _keep_fields:
          continue
        # cribbed from attr/_make.py; the goal is to compute the attribute's
        # default value.
        if isinstance(attrib.default, attr.Factory):
          if attrib.default.takes_self:
            val = attrib.default.factory(self)
          else:
            val = attrib.default.factory()
        else:
          val = attrib.default
        if attrib.converter:
          val = attrib.converter(val)
        object.__setattr__(self, attrib.name, val)
      return

    if self.ok_ret is not self.ALL_OK:
      object.__setattr__(self, 'ok_ret', frozenset(self.ok_ret))
    object.__setattr__(self, 'env', freeze(self.env))

    # Ensure that output placeholders don't have ambiguously overlapping names.
    placeholders = set()
    collisions = set()
    ns_str = None
    for itm in self.cmd:
      if isinstance(itm, OutputPlaceholder):
        key = itm.namespaces, itm.name
        if key in placeholders:
          ns_str = '.'.join(itm.namespaces)
          if itm.name is None:
            collisions.add("{} unnamed".format(ns_str))
          else:
            collisions.add("{} named {!r}".format(ns_str, itm.name))
        else:
          placeholders.add(key)

    if collisions:
      raise ValueError(
          'Found conflicting Placeholders: {!r}. Please give these placeholders'
          ' unique "name"s and access them like `step_result.{}s[name]`.'
          .format(list(collisions), ns_str))


  # Used with to indicate that all retcodes values are acceptable.
  ALL_OK = sentinel('ALL_OK')

  _RENDER_WHITELIST=frozenset((
    'cmd',
  ))

  _RENDER_BLACKLIST=frozenset((
    'name_tokens',
    'ok_ret',
    'step_test_data',
    'env_prefixes',
    'env_suffixes',
    'trigger_specs',
  ))

  @property
  def name(self):
    """Returns a '.' separated string version of name_tokens for backwards
    compatibility with old recipe engine code."""
    # TODO(iannucci): Remove this method or make it use '|' separators
    # instead.
    return '.'.join(self.name_tokens)

  def _asdict(self):
    ret = thaw(attr.asdict(self, filter=(lambda attr, val: (
      (val or (attr.name in self._RENDER_WHITELIST)) and
      attr.name not in self._RENDER_BLACKLIST
    ))))
    if self.env_prefixes.mapping:
      ret['env_prefixes'] = dict(self.env_prefixes.mapping)
    if self.env_suffixes.mapping:
      ret['env_suffixes'] = dict(self.env_suffixes.mapping)
    if self.trigger_specs:
      ret['trigger_specs'] = [ts._asdict() for ts in self.trigger_specs]
    ret['name'] = self.name
    return ret
