from .ports import DPRX, DPTX, HDRX, HDTX, PDC340
from .modules import MemoryManager, Capturer, DUTTests
from UniTAP.libs.lib_tsi.tsi_io import DeviceIO, PortProtocol


class UCD340:
    """
    Class `UCD340` describes of device UCD-340. Device has several possible role:
    - 'USB-C, DP Alt Mode Reference Sink' `USBCSink`
    - 'USB-C, DP Alt Mode Reference Source' `USBCSource`.
    """
    class USBCSink:
        """
        Class `USBCSink` contains information of available functionality modules for role USB-C Sink (RX - receiver)
        role:
        - `DPRX`.
        - `DUTTests`.
        - `PDC`.
        """
        def __init__(self, dev_io: DeviceIO, memory_manager: MemoryManager, capturer: Capturer):
            self.__port_io = dev_io.create_port_io(0, PortProtocol.DisplayPortThrowUSBC)
            self.__dprx = DPRX(self.__port_io, memory_manager, capturer)
            self.__dut_tests = DUTTests(dev_io)
            self.__pdcrx = PDC340(self.__port_io)

        @property
        def dprx(self) -> DPRX:
            """
            Returns DP Sink (RX - receiver) role.

            Returns:
                object of DPRX type.
            """
            return self.__dprx

        @property
        def pdcrx(self) -> PDC340:
            """
            Returns PDC Sink (RX - receiver) role.

            Returns:
                object of `PDC340` type.
            """
            return self.__pdcrx

        @property
        def dut_tests(self) -> DUTTests:
            """
            Returns DUT Test module.

            Returns:
                object of DUTTests type.
            """
            return self.__dut_tests

        @property
        def name(self) -> str:
            """
            Returns name of role.

            Returns:
                object of str type.
            """
            return list(UCD340.ROLE_DICT.keys())[list(UCD340.ROLE_DICT.values()).index(type(self))]

    class USBCSource:
        """
        Class `USBCSource` contains information of available functionality modules for role USB-C Source
        (TX - transmitter) role:
        - `DPTX`.
        - `DUTTests`.
        - `PDC`.
        """
        def __init__(self, dev_io: DeviceIO, memory_manager: MemoryManager, capturer: Capturer):
            self.__port_io = dev_io.create_port_io(0, PortProtocol.DisplayPortThrowUSBC)
            self.__dptx = DPTX(self.__port_io, memory_manager, capturer)
            self.__dut_tests = DUTTests(dev_io)
            self.__pdctx = PDC340(self.__port_io)

        @property
        def dptx(self) -> DPTX:
            """
            Returns DP Source (TX - transmitter) role.

            Returns:
                object of DPTX type.
            """
            return self.__dptx

        @property
        def pdctx(self) -> PDC340:
            """
            Returns PDC Source (TX - transmitter) role.

            Returns:
                object of `PDC340` type.
            """
            return self.__pdctx

        @property
        def dut_tests(self) -> DUTTests:
            """
            Returns DUT Test module.

            Returns:
                object of DUTTests type.
            """
            return self.__dut_tests

        @property
        def name(self) -> str:
            """
            Returns name of role.

            Returns:
                object of str type.
            """
            return list(UCD340.ROLE_DICT.keys())[list(UCD340.ROLE_DICT.values()).index(type(self))]

    ROLE_DICT = {
        "USB-C, DP Alt Mode Reference Sink": USBCSink,
        "USB-C, DP Alt Mode Reference Source": USBCSource
    }


class UCD240(UCD340):
    """
    Class `UCD240` describes of device UCD-240 and have the same functionality as the class 'UCD340'.
    Device has several possible role:
    - 'USB-C, DP Alt Mode Reference Sink' `USBCSink`
    - 'USB-C, DP Alt Mode Reference Source' `USBCSource`.
    """


class UCD323:
    """
    Class `UCD323` describes of device UCD-323. Device has several possible role:
    - 'DisplayPort Reference Sink (SST, HDCP 2.3)' `DPSink`
    - 'DisplayPort Reference Source (SST, HDCP 2.3)' `DPSource`
    - 'HDMI Reference Sink (HDCP 2.3)' `HDMISink`
    - 'HDMI Reference Source (HDCP 2.3)' `HDMISource`
    """
    class DPSink:
        """
        Class `DPSink` contains information of available functionality modules for role DP Sink (RX - receiver) role:
        - `DPRX`.
        - `DUTTests`.
        """
        def __init__(self, dev_io: DeviceIO, memory_manager: MemoryManager, capturer: Capturer):
            self.__dprx = DPRX(dev_io.create_port_io(0, PortProtocol.DisplayPort), memory_manager, capturer)
            self.__dut_tests = DUTTests(dev_io)

        @property
        def dprx(self) -> DPRX:
            """
            Returns DP Sink (RX - receiver) role.

            Returns:
                object of DPRX type.
            """
            return self.__dprx

        @property
        def dut_tests(self) -> DUTTests:
            """
            Returns DUT Test module.

            Returns:
                object of DUTTests type.
            """
            return self.__dut_tests

        @property
        def name(self) -> str:
            """
            Returns name of role.

            Returns:
                object of str type.
            """
            return list(UCD323.ROLE_DICT.keys())[list(UCD323.ROLE_DICT.values()).index(type(self))]

    class DPSource:
        """
        Class `DPSink` contains information of available functionality modules for role DP Source (TX - transmitter)
        role:
        - `DPTX`.
        - `DUTTests`.
        """
        def __init__(self, dev_io: DeviceIO, memory_manager: MemoryManager, capturer: Capturer):
            self.__dptx = DPTX(dev_io.create_port_io(0, PortProtocol.DisplayPort), memory_manager, capturer)
            self.__dut_tests = DUTTests(dev_io)

        @property
        def dptx(self) -> DPTX:
            """
            Returns DP Source (TX - transmitter) role.

            Returns:
                object of DPTX type.
            """
            return self.__dptx

        @property
        def dut_tests(self) -> DUTTests:
            """
            Returns DUT Test module.

            Returns:
                object of DUTTests type.
            """
            return self.__dut_tests

        @property
        def name(self) -> str:
            """
            Returns name of role.

            Returns:
                object of str type.
            """
            return list(UCD323.ROLE_DICT.keys())[list(UCD323.ROLE_DICT.values()).index(type(self))]

    class HDMISink:
        """
        Class `HDMISink` contains information of available functionality modules for role HDMI Sink (RX - receiver)
        role:
        - `HDRX`.
        - `DUTTests`.
        """
        def __init__(self, dev_io: DeviceIO, memory_manager: MemoryManager, capturer: Capturer):
            self.__hdrx = HDRX(dev_io.create_port_io(0, PortProtocol.HDMI), memory_manager, capturer)
            self.__dut_tests = DUTTests(dev_io)

        @property
        def hdrx(self) -> HDRX:
            """
            Returns HDMI Sink (RX - receiver) role.

            Returns:
                object of HDRX type.
            """
            return self.__hdrx

        @property
        def dut_tests(self) -> DUTTests:
            """
            Returns DUT Test module.

            Returns:
                object of DUTTests type.
            """
            return self.__dut_tests

        @property
        def name(self) -> str:
            """
            Returns name of role.

            Returns:
                object of str type.
            """
            return list(UCD323.ROLE_DICT.keys())[list(UCD323.ROLE_DICT.values()).index(type(self))]

    class HDMISource:
        """
        Class `HDMISource` contains information of available functionality modules for role HDMI Source
        (TX - transmitter) role:
        - `HDTX`.
        - `DUTTests`.
        """
        def __init__(self, dev_io: DeviceIO, memory_manager: MemoryManager, capturer: Capturer):
            self.__hdtx = HDTX(dev_io.create_port_io(0, PortProtocol.HDMI), memory_manager, capturer)
            self.__dut_tests = DUTTests(dev_io)

        @property
        def hdtx(self) -> HDTX:
            """
            Returns HDMI Source (TX - transmitter) role.

            Returns:
                object of HDTX type.
            """
            return self.__hdtx

        @property
        def dut_tests(self) -> DUTTests:
            """
            Returns DUT Test module.

            Returns:
                object of DUTTests type.
            """
            return self.__dut_tests

        @property
        def name(self) -> str:
            """
            Returns name of role.

            Returns:
                object of str type.
            """
            return list(UCD323.ROLE_DICT.keys())[list(UCD323.ROLE_DICT.values()).index(type(self))]

    ROLE_DICT = {
        "DisplayPort Reference Sink (SST, HDCP 2.3)": DPSink,
        "DisplayPort Reference Source (SST, HDCP 2.3)": DPSource,
        "HDMI Reference Sink (HDCP 2.3)": HDMISink,
        "HDMI Reference Source (HDCP 2.3)": HDMISource,
    }


class UCD301:
    """
    Class `UCD301` describes of device UCD-301. Device has several possible role:
    - 'DisplayPort Reference Sink (SST, HDCP 2.3)' `DPSink`
    - 'HDMI Reference Sink (HDCP 2.3)' `HDMISink`
    """
    class DPSink:
        """
        Class `DPSink` contains information of available functionality modules for role DP Sink (RX - receiver) role:
        - `DPRX`.
        - `DUTTests`.
        """
        def __init__(self, dev_io: DeviceIO, memory_manager: MemoryManager, capturer: Capturer):
            self.__dprx = DPRX(dev_io.create_port_io(0, PortProtocol.DisplayPort), memory_manager, capturer)
            self.__dut_tests = DUTTests(dev_io)

        @property
        def dprx(self) -> DPRX:
            """
            Returns DP Sink (RX - receiver) role.

            Returns:
                object of DPRX type.
            """
            return self.__dprx

        @property
        def dut_tests(self) -> DUTTests:
            """
            Returns DUT Test module.

            Returns:
                object of DUTTests type.
            """
            return self.__dut_tests

        @property
        def name(self) -> str:
            """
            Returns name of role.

            Returns:
                object of str type.
            """
            return list(UCD301.ROLE_DICT.keys())[list(UCD301.ROLE_DICT.values()).index(type(self))]

    class HDMISink:
        """
        Class `HDMISink` contains information of available functionality modules for role HDMI Sink (RX - receiver)
        role:
        - `HDRX`.
        - `DUTTests`.
        """
        def __init__(self, dev_io: DeviceIO, memory_manager: MemoryManager, capturer: Capturer):
            self.__hdrx = HDRX(dev_io.create_port_io(0, PortProtocol.HDMI), memory_manager, capturer)
            self.__dut_tests = DUTTests(dev_io)

        @property
        def hdrx(self) -> HDRX:
            """
            Returns HDMI Sink (RX - receiver) role.

            Returns:
                object of HDRX type.
            """
            return self.__hdrx

        @property
        def dut_tests(self) -> DUTTests:
            """
            Returns DUT Test module.

            Returns:
                object of DUTTests type.
            """
            return self.__dut_tests

        @property
        def name(self) -> str:
            """
            Returns name of role.

            Returns:
                object of str type.
            """
            return list(UCD301.ROLE_DICT.keys())[list(UCD301.ROLE_DICT.values()).index(type(self))]

    class DPSinkHDMISink:
        """
        Class `DPSinkHDMISink` contains information of available functionality modules for role DP and HDMI Sink
        (RX - receiver) role:
        - `DPRX`.
        - `HDRX`.
        - `DUTTests`.
        """

        def __init__(self, dev_io: DeviceIO, memory_manager: MemoryManager, capturer: Capturer):
            self.__dprx = DPRX(dev_io.create_port_io(0, PortProtocol.DisplayPort), memory_manager, capturer)
            self.__hdrx = HDRX(dev_io.create_port_io(0, PortProtocol.HDMI), memory_manager, capturer)
            self.__dut_tests = DUTTests(dev_io)

        @property
        def hdrx(self) -> HDRX:
            """
            Returns HDMI Sink (RX - receiver) role.

            Returns:
                object of HDRX type.
            """
            return self.__hdrx

        @property
        def dprx(self) -> DPRX:
            """
            Returns DP Sink (RX - receiver) role.

            Returns:
                object of DPRX type.
            """
            return self.__dprx

        @property
        def dut_tests(self) -> DUTTests:
            """
            Returns DUT Test module.

            Returns:
                object of DUTTests type.
            """
            return self.__dut_tests

        @property
        def name(self) -> str:
            """
            Returns name of role.

            Returns:
                object of str type.
            """
            return list(UCD301.ROLE_DICT.keys())[list(UCD301.ROLE_DICT.values()).index(type(self))]

    ROLE_DICT = {
        "DisplayPort Reference Sink (SST, HDCP 2.3)": DPSink,
        "HDMI, DisplayPort (SST), SPDIF Reference Sink": DPSinkHDMISink,
        "HDMI Reference Sink (HDCP 2.3)": HDMISink,
    }
