from enum import IntEnum
from UniTAP.common.video_mode import VideoMode


class VCPStatus:
    """
    Class `VCPStatus` describes МСЗ status. Contains following information:
    - Port number.
    - Stream ID.
    - Requested PBN.
    - Allocated PBN.
    - Number of slots allocated for VC.
    - Number of first time slot allocated for VC.
    """
    def __init__(self):
        self.port_number = 0
        self.stream_id = 0
        self.req_pbn = 0
        self.alloc_pbn = 0
        self.first_slot = 0
        self.slot_num = 0

    def __eq__(self, other):
        return self.port_number == other.port_number and \
               self.stream_id == other.stream_id and \
               self.req_pbn == other.req_pbn and \
               self.alloc_pbn == other.alloc_pbn and \
               self.first_slot == other.first_slot and \
               self.slot_num == other.slot_num

    def __str__(self) -> str:
        return f"Port #     - {self.port_number}\n" \
               f"SID        - {self.stream_id}\n" \
               f"REQ PBN    - {self.req_pbn}\n" \
               f"Alloc PBN  - {self.alloc_pbn}\n" \
               f"First Slot - {self.first_slot}\n" \
               f"Slot num   - {self.slot_num}\n"


class DpLinkEncoding(IntEnum):
    """
    Class `DpLinkEncoding` contains all possible variants of DP link encoding.
    """
    LE_NONE = 0
    LE_8b10b = 1
    LE_128b132b = 2

    def __str__(self):
        if self.value == DpLinkEncoding.LE_NONE:
            return "None"
        elif self.value == DpLinkEncoding.LE_8b10b:
            return "8b/10b"
        elif self.value == DpLinkEncoding.LE_128b132b:
            return "128b/132b"
        else:
            return "Invalid"


class DpLinkTrainingResult(IntEnum):
    """
    Class `DpLinkTrainingResult` contains all possible variants of Link training results.
    """
    LTR_NOT_STARTED = 0
    LTR_IN_PROGRESS = 1
    LTR_FAIL = 2
    LTR_SUCCESS = 3


class LaneStatus:
    """
    Class `LaneStatus` describes lane status. Contains following information:
    - CR state.
    - SL state.
    - EQ state.
    - Voltage swing value.
    - Pre Emphasis value.
    - FFE preset value.
    - Error count.
    """
    def __init__(self):
        self.cr = False
        self.sl = False
        self.eq = False
        self.voltage_swing = 0
        self.pre_emphasis = 0
        self.ffe_preset = 0
        self.error_count = 0

    def __eq__(self, other) -> bool:
        return self.cr == other.cr and \
               self.sl == other.sl and \
               self.eq == other.eq and \
               self.voltage_swing == other.voltage_swing and \
               self.pre_emphasis == other.pre_emphasis and \
               self.ffe_preset == other.ffe_preset and \
               self.error_count == other.error_count

    def __str__(self) -> str:
        return f"CR - {bool(self.cr)}\nSL - {bool(self.sl)}\nEQ - {bool(self.eq)}\n" \
               f"Voltage Swing - {self.voltage_swing}\n" \
               f"Pre Emphasis - {self.pre_emphasis}\nFFE Preset - {self.ffe_preset}\nError count - {self.error_count}\n"


class SdpCrc16:
    """
    Class `SdpCrc16` describes SDP CRC16 errors on the stream. It contains 'State' - enabled or disabled, and errors -
    count of the errors on the stream.
    """
    def __init__(self):
        self.state = False
        self.errors = 0

    def __eq__(self, other) -> bool:
        return self.state == other.state and self.errors == other.errors

    def __str__(self) -> str:
        return f"State: {'Enabled' if self.state else 'Disabled'}\n" \
               f"Errors: {hex(self.errors)}"


class StreamStatus:
    """
    Class `StreamStatus` describes stream status. Contains following information:
    - Video mode `VideoMode`.
    - CRC value of stream.
    - DSC CRC value of stream.
    - SDP CRC16 error of stream
    """
    def __init__(self):
        self.video_mode = VideoMode()
        self.crc = [0, 0, 0]
        self.dsc_crc = [0, 0, 0]
        self.sdp_crc16 = SdpCrc16()

    def __str__(self) -> str:
        return f"Video mode:\n{self.video_mode.__str__()}\n" \
               f"CRC: r - {self.crc[0]}, g - {self.crc[1]}, b - {self.crc[2]}\n" \
               f"DSC CRC: r - {self.dsc_crc[0]}, g - {self.dsc_crc[1]}, b - {self.dsc_crc[2]}\n"


class StreamStatusDP(StreamStatus):
    """
    The `StreamStatusDP` class inherited from the `StreamStatus` class and contains all the functionality.
    - MVID
    - NVID
    - VFREQ `vfreq`
    """
    def __init__(self):
        super().__init__()
        self.mvid = 0
        self.nvid = 0

    @property
    def vfreq(self) -> int:
        """
        Return value of VFREQ.

        Returns:
            object of `int` type

        """
        return ((self.mvid & 0xFFFFFF) << 24) | (self.nvid & 0xFFFFFF)

    def __str__(self) -> str:
        return f"Video mode:\n{self.video_mode.__str__()}\n" \
               f"CRC: r - {self.crc[0]}, g - {self.crc[1]}, b - {self.crc[2]}\n" \
               f"DSC CRC: r - {self.dsc_crc[0]}, g - {self.dsc_crc[1]}, b - {self.dsc_crc[2]}\n" \
               f"MVID / NVID - {self.mvid:06X} / {self.nvid:06X}\n" \
               f"VFREQ - {self.vfreq}\n"


DP21_LinkRate = {1: 10.0, 2: 20.0, 4: 13.5}
DP21_LinkRateRev = {10.0: 1, 20.0: 2, 13.5: 4}
