# 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(object):
  """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
