"""
Created on Feb 17 2018

@author: MCC
"""
from ctypes import c_longlong, byref
from .ul_exception import ULException
from .ul_c_interface import lib, DioInfoItem, DioConfigItem
from .ul_enums import DigitalDirection, ULError, DigitalPortType


class DioConfig:
    """
    An instance of the DioConfig class is obtained by
    calling :func:`DioDevice.get_config`.
    """

    def __init__(self, handle):
        self.__handle = handle

    def get_port_direction(self, port_type):
        # type: (DigitalPortType) -> list[DigitalDirection]
        """
        Gets the configured direction for each bit in the specified port
        for the device referenced by the :class:`DioInfo` object object.

        Args:
            port_type (DigitalPortType): The digital port type whose
                direction is being determined.

        Returns:
            list[DigitalDirection]:

            A list of values that specify
            the direction of each bit in the specified port.

        Raises:
            :class:`ULException`
        """
        bit_direction_mask = c_longlong()
        num_bits = c_longlong()
        port_types_list = []
        number_of_ports = c_longlong()
        bit_mask = 1
        bit_direction_list = []

        err = lib.ulDIOGetInfo(self.__handle, DioInfoItem.NUM_PORTS, 0, byref(number_of_ports))
        if err != 0:
            raise ULException(err)

        # get the supported port types
        type_of_port = c_longlong()
        for i in range(number_of_ports.value):
            err = lib.ulDIOGetInfo(self.__handle, DioInfoItem.PORT_TYPE, i, byref(type_of_port))
            if err != 0:
                raise ULException(err)

            port_types_list.append(type_of_port.value)

        # get the index for the port type
        if port_type in port_types_list:
            port_index = port_types_list.index(port_type)

            err = lib.ulDIOGetInfo(self.__handle, DioInfoItem.NUM_BITS, port_index, byref(num_bits))
            if err != 0:
                raise ULException(err)

            err = lib.ulDIOGetConfig(self.__handle, DioConfigItem.DIO_CFG_PORT_DIRECTION_MASK, port_index,
                                     byref(bit_direction_mask))
            if err != 0:
                raise ULException(err)

            for bit_num in range(num_bits.value):
                if bit_direction_mask.value & bit_mask:
                    bit_direction_list.append(DigitalDirection.OUTPUT)
                else:
                    bit_direction_list.append(DigitalDirection.INPUT)
        else:
            raise ULException(ULError.BAD_PORT_TYPE)

        return bit_direction_list
