# Copyright 2016 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.
"""Controller module for attenuators.

Sample Config:

.. code-block:: python

    "Attenuator": [
        {
            "address": "192.168.1.12",
            "port": 23,
            "model": "minicircuits",
            "paths": ["AP1-2G", "AP1-5G", "AP2-2G", "AP2-5G"]
        },
        {
            "address": "192.168.1.14",
            "port": 23,
            "model": "minicircuits",
            "paths": ["AP-DUT"]
        }
    ]
"""
import importlib
import logging

MOBLY_CONTROLLER_CONFIG_NAME = "Attenuator"
# Keys used inside a config dict for attenuator.
# Keys for making the connection to the attenuator device. Right now we only
# use telnet lib. This can be refactored when the need for a different
# communication protocol arises.
KEY_ADDRESS = "address"
KEY_PORT = "port"
# A string that is the model of the attenuator used. This is essentially the
# module name for the underlying driver for the attenuator hardware.
KEY_MODEL = "model"
# A list of strings, each describing what's the connected to this attenuation
# path
KEY_PATHS = "paths"

PACKAGE_PATH_TEMPLATE = "mobly.controllers.attenuator_lib.%s"


def create(configs):
  objs = []
  for config in configs:
    _validate_config(config)
    attenuator_model = config[KEY_MODEL]
    # Import the correct driver module for the attenuator device
    module_name = PACKAGE_PATH_TEMPLATE % attenuator_model
    module = importlib.import_module(module_name)
    # Create each
    attenuation_device = module.AttenuatorDevice(
        path_count=len(config[KEY_PATHS]))
    attenuation_device.model = attenuator_model
    instances = attenuation_device.open(config[KEY_ADDRESS], config[KEY_PORT])
    for idx, path_name in enumerate(config[KEY_PATHS]):
      path = AttenuatorPath(attenuation_device, idx=idx, name=path_name)
      objs.append(path)
  return objs


def destroy(objs):
  for attenuation_path in objs:
    attenuation_path.attenuation_device.close()


class Error(Exception):
  """This is the Exception class defined for all errors generated by
    Attenuator-related modules.
    """


def _validate_config(config):
  """Verifies that a config dict for an attenuator device is valid.

    Args:
        config: A dict that is the configuration for an attenuator device.

    Raises:
        attenuator.Error: A config is not valid.
    """
  required_keys = [KEY_ADDRESS, KEY_MODEL, KEY_PORT, KEY_PATHS]
  for key in required_keys:
    if key not in config:
      raise Error("Required key %s missing from config %s", (key, config))


class AttenuatorPath:
  """A convenience class that allows users to control each attenuator path
    separately as different objects, as opposed to passing in an index number
    to the functions of an attenuator device object.

    This decouples the test code from the actual attenuator device used in the
    physical test bed.

    For example, if a test needs to attenuate four signal paths, this allows the
    test to do:

    .. code-block:: python

        self.attenuation_paths[0].set_atten(50)
        self.attenuation_paths[1].set_atten(40)

    instead of:

    .. code-block:: python

        self.attenuators[0].set_atten(0, 50)
        self.attenuators[0].set_atten(1, 40)

    The benefit the former is that the physical test bed can use either four
    single-channel attenuators, or one four-channel attenuators. Whereas the
    latter forces the test bed to use a four-channel attenuator.
    """

  def __init__(self, attenuation_device, idx=0, name=None):
    self.model = attenuation_device.model
    self.attenuation_device = attenuation_device
    self.idx = idx
    if (self.idx >= attenuation_device.path_count):
      raise IndexError("Attenuator index out of range!")

  def set_atten(self, value):
    """This function sets the attenuation of Attenuator.

        Args:
            value: This is a floating point value for nominal attenuation to be
                set. Unit is db.
        """
    self.attenuation_device.set_atten(self.idx, value)

  def get_atten(self):
    """Gets the current attenuation setting of Attenuator.

        Returns:
            A float that is the current attenuation value. Unit is db.
        """

    return self.attenuation_device.get_atten(self.idx)

  def get_max_atten(self):
    """Gets the max attenuation supported by the Attenuator.

        Returns:
            A float that is the max attenuation value.
        """
    return self.attenuation_device.max_atten
