# -*- coding: utf-8 -*-
# Copyright 2019 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.

"""Validation helpers for simple input validation in the API.

Note: Every validator MUST respect config.do_validation. This is an internally
set config option that allows the mock call decorators to be placed before or
after the validation decorators, rather than forcing an ordering that could then
produce incorrect outputs if missed.
"""

from __future__ import print_function

import functools
import os
import sys

from google.protobuf import message as protobuf_message

from chromite.lib import cros_build_lib
from chromite.lib import cros_logging as logging


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


def _value(field, message):
  """Helper function to fetch the value of the field.

  Args:
    field (str): The field name. Can be nested via . separation.
    message (Message): The protobuf message it is being fetched from.

  Returns:
    str|None|int|list|Message|bool - The value of the field.
  """
  value = message
  for part in field.split('.'):
    if not isinstance(value, protobuf_message.Message):
      value = None
      break

    try:
      value = getattr(value, part)
    except AttributeError as e:
      cros_build_lib.Die('Invalid field: %s', e)

  return value


# pylint: disable=docstring-misnamed-args
def exists(*fields):
  """Validate that the paths in |fields| exist.

  Args:
    fields (str): The fields being checked. Can be . separated nested
      fields.
  """
  assert fields

  def decorator(func):
    @functools.wraps(func)
    def _exists(input_proto, output_proto, config, *args, **kwargs):
      if config.do_validation:
        for field in fields:
          logging.debug('Validating %s exists.', field)

          value = _value(field, input_proto)
          if not value or not os.path.exists(value):
            cros_build_lib.Die('%s path does not exist: %s' % (field, value))

      return func(input_proto, output_proto, config, *args, **kwargs)

    return _exists

  return decorator


def is_in(field, values):
  """Validate |field| contains |value|.

  Args:
    field (str): The field being checked. May be . separated nested fields.
    values (list): The possible values field may take.
  """
  assert field
  assert values

  def decorator(func):
    @functools.wraps(func)
    def _is_in(input_proto, output_proto, config, *args, **kwargs):
      if config.do_validation:
        logging.debug('Validating %s is in %r', field, values)
        value = _value(field, input_proto)

        if value not in values:
          cros_build_lib.Die('%s (%r) must be in %r', field, value, values)

      return func(input_proto, output_proto, config, *args, **kwargs)

    return _is_in

  return decorator


# pylint: disable=docstring-misnamed-args
def require(*fields):
  """Verify |fields| have all been set.

  Args:
    fields (str): The fields being checked. May be . separated nested fields.
  """
  assert fields

  def decorator(func):
    @functools.wraps(func)
    def _require(input_proto, output_proto, config, *args, **kwargs):
      if config.do_validation:
        for field in fields:
          logging.debug('Validating %s is set.', field)

          value = _value(field, input_proto)
          if not value:
            cros_build_lib.Die('%s is required.', field)

      return func(input_proto, output_proto, config, *args, **kwargs)

    return _require

  return decorator


def require_each(field, subfields, allow_empty=True):
  """Verify |field| each have all of the |subfields| set.

  When |allow_empty| is True, |field| may be empty, and |subfields| are only
  validated when it is not empty. When |allow_empty| is False, |field| must
  also have at least one entry.

  Args:
    field (str): The repeated field being checked. May be . separated nested
        fields.
    subfields (list[str]): The fields of the repeated message to validate.
    allow_empty (bool): Also require at least one entry in the repeated field.
  """
  assert field
  assert subfields
  assert not isinstance(subfields, str)

  def decorator(func):
    @functools.wraps(func)
    def _require_each(input_proto, output_proto, config, *args, **kwargs):
      if config.do_validation:
        members = _value(field, input_proto) or []
        if not allow_empty and not members:
          cros_build_lib.Die('The %s field is empty.', field)
        for member in members:
          for subfield in subfields:
            logging.debug('Validating %s.[each].%s is set.', field, subfield)
            value = _value(subfield, member)
            if not value:
              cros_build_lib.Die('%s is required.', field)

      return func(input_proto, output_proto, config, *args, **kwargs)

    return _require_each

  return decorator


def validation_complete(func):
  """Automatically skip the endpoint when called after all other validators.

  This decorator MUST be applied after all other validate decorators.
  The config can be checked manually if there is non-decorator validation, but
  this is much cleaner if it is all done in decorators.
  """

  @functools.wraps(func)
  def _validate_only(request, response, configs, *args, **kwargs):
    if configs.validate_only:
      # Avoid calling the endpoint.
      return 0
    else:
      return func(request, response, configs, *args, **kwargs)

  return _validate_only
