# Copyright 2018 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
""" Module for Mobly controller management."""
import collections
import copy
import logging
import yaml

from mobly import expects
from mobly import records
from mobly import signals


def verify_controller_module(module):
  """Verifies a module object follows the required interface for
  controllers.

  The interface is explained in the docstring of
  `base_test.BaseTestClass.register_controller`.

  Args:
    module: An object that is a controller module. This is usually
      imported with import statements or loaded by importlib.

  Raises:
    ControllerError: if the module does not match the Mobly controller
      interface, or one of the required members is null.
  """
  required_attributes = ('create', 'destroy', 'MOBLY_CONTROLLER_CONFIG_NAME')
  for attr in required_attributes:
    if not hasattr(module, attr):
      raise signals.ControllerError(
        'Module %s missing required controller module attribute'
        ' %s.' % (module.__name__, attr))
    if not getattr(module, attr):
      raise signals.ControllerError(
        'Controller interface %s in %s cannot be null.' %
        (attr, module.__name__))


class ControllerManager(object):
  """Manages the controller objects for Mobly tests.

  This manages the life cycles and info retrieval of all controller objects
  used in a test.

  Attributes:
    controller_configs: dict, controller configs provided by the user via
      test bed config.
  """

  def __init__(self, class_name, controller_configs):
    # Controller object management.
    self._controller_objects = collections.OrderedDict(
    )  # controller_name: objects
    self._controller_modules = {}  # controller_name: module
    self._class_name = class_name
    self.controller_configs = controller_configs

  def register_controller(self, module, required=True, min_number=1):
    """Loads a controller module and returns its loaded devices.

    This is to be used in a mobly test class.

    Args:
      module: A module that follows the controller module interface.
      required: A bool. If True, failing to register the specified
        controller module raises exceptions. If False, the objects
        failed to instantiate will be skipped.
      min_number: An integer that is the minimum number of controller
        objects to be created. Default is one, since you should not
        register a controller module without expecting at least one
        object.

    Returns:
      A list of controller objects instantiated from controller_module, or
      None if no config existed for this controller and it was not a
      required controller.

    Raises:
      ControllerError:
        * The controller module has already been registered.
        * The actual number of objects instantiated is less than the
        * `min_number`.
        * `required` is True and no corresponding config can be found.
        * Any other error occurred in the registration process.
    """
    verify_controller_module(module)
    # Use the module's name as the ref name
    module_ref_name = module.__name__.split('.')[-1]
    if module_ref_name in self._controller_objects:
      raise signals.ControllerError(
        'Controller module %s has already been registered. It cannot '
        'be registered again.' % module_ref_name)
    # Create controller objects.
    module_config_name = module.MOBLY_CONTROLLER_CONFIG_NAME
    if module_config_name not in self.controller_configs:
      if required:
        raise signals.ControllerError(
          'No corresponding config found for %s' %
          module_config_name)
      logging.warning(
        'No corresponding config found for optional controller %s',
        module_config_name)
      return None
    try:
      # Make a deep copy of the config to pass to the controller module,
      # in case the controller module modifies the config internally.
      original_config = self.controller_configs[module_config_name]
      controller_config = copy.deepcopy(original_config)
      objects = module.create(controller_config)
    except:
      logging.exception(
        'Failed to initialize objects for controller %s, abort!',
        module_config_name)
      raise
    if not isinstance(objects, list):
      raise signals.ControllerError(
        'Controller module %s did not return a list of objects, abort.'
        % module_ref_name)
    # Check we got enough controller objects to continue.
    actual_number = len(objects)
    if actual_number < min_number:
      module.destroy(objects)
      raise signals.ControllerError(
        'Expected to get at least %d controller objects, got %d.' %
        (min_number, actual_number))
    # Save a shallow copy of the list for internal usage, so tests can't
    # affect internal registry by manipulating the object list.
    self._controller_objects[module_ref_name] = copy.copy(objects)
    logging.debug('Found %d objects for controller %s', len(objects),
            module_config_name)
    self._controller_modules[module_ref_name] = module
    return objects

  def unregister_controllers(self):
    """Destroy controller objects and clear internal registry.

    This will be called after each test class.
    """
    # TODO(xpconanfan): actually record these errors instead of just
    # logging them.
    for name, module in self._controller_modules.items():
      logging.debug('Destroying %s.', name)
      with expects.expect_no_raises('Exception occurred destroying %s.' %
                      name):
        module.destroy(self._controller_objects[name])
    self._controller_objects = collections.OrderedDict()
    self._controller_modules = {}

  def _create_controller_info_record(self, controller_module_name):
    """Creates controller info record for a particular controller type.

    Info is retrieved from all the controller objects spawned from the
    specified module, using the controller module's `get_info` function.

    Args:
      controller_module_name: string, the name of the controller module
        to retrieve info from.

    Returns:
      A records.ControllerInfoRecord object.
    """
    module = self._controller_modules[controller_module_name]
    controller_info = None
    try:
      controller_info = module.get_info(
        copy.copy(self._controller_objects[controller_module_name]))
    except AttributeError:
      logging.warning(
        'No optional debug info found for controller '
        '%s. To provide it, implement `get_info`.',
        controller_module_name)
    try:
      yaml.dump(controller_info)
    except TypeError:
      logging.warning(
        'The info of controller %s in class "%s" is not '
        'YAML serializable! Coercing it to string.',
        controller_module_name, self._class_name)
      controller_info = str(controller_info)
    return records.ControllerInfoRecord(
      self._class_name, module.MOBLY_CONTROLLER_CONFIG_NAME,
      controller_info)

  def get_controller_info_records(self):
    """Get the info records for all the controller objects in the manager.

    New info records for each controller object are created for every call
    so the latest info is included.

    Returns:
      List of records.ControllerInfoRecord objects. Each opject conatins
      the info of a type of controller
    """
    info_records = []
    for controller_module_name in self._controller_objects.keys():
      with expects.expect_no_raises(
          'Failed to collect controller info from %s' %
          controller_module_name):
        record = self._create_controller_info_record(
          controller_module_name)
        if record:
          info_records.append(record)
    return info_records
