# 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
