from ctypes import Structure, c_uint32, c_uint16
from enum import IntEnum
from .pr_types import Flags, Region


class PrControl(IntEnum):
    Disable = 0
    EnableInactiveMode = 1
    EnableActiveMode = 2
    EnableSelectiveUpdate = 3
    FullScreenLiveFrameUpdate = 4


class PrConfig(Structure):
    _fields_ = [
        ("early_transport", c_uint32, 1),
        ("crc_in_vsc_sdp", c_uint32, 1),
        ('mode', c_uint32, 2),
        ('hpd_irq_as_sdp', c_uint32, 1),
        ('hpd_irq_vsc_sdp', c_uint32, 1),
        ('hpd_irq_rfb', c_uint32, 1),
        ('hpd_irq_crc', c_uint32, 1),
        ('self_refresh', c_uint32, 1),
        ('ext_y_granularity', c_uint32, 1),
        ('main_link_on', c_uint32, 1),
        ("y_gran_value", c_uint32, 4),
        ('reserved', c_uint32, 17)
    ]

    @property
    def value(self) -> int:
        return (self.early_transport | self.crc_in_vsc_sdp << 1 | self.mode << 3 | self.hpd_irq_as_sdp << 4 |
                self.hpd_irq_vsc_sdp << 5 | self.hpd_irq_rfb << 6 | self.hpd_irq_crc << 7 | self.self_refresh << 8 |
                self.ext_y_granularity << 9 | self.main_link_on << 10 | self.y_gran_value << 13)


class RegionConfig(Structure):
    _fields_ = [
        ("x", c_uint32, 16),
        ("y", c_uint32, 16),
        ('width', c_uint32, 16),
        ('height', c_uint32, 16),
    ]

    @property
    def value(self) -> list:
        return [self.x | self.y << 16, self.width | self.height << 16]

    @value.setter
    def value(self, config: Region):
        self.x = config.x
        self.y = config.y
        self.width = config.width
        self.height = config.height


class PatternCaps(IntEnum):
    PrNotSupported = 0
    PrOnly = 1
    PrSelectiveUpdate = 2
    PrSelectiveUpdateEarlyTransport = 3


class PRCaps(Structure):
    class PRFlags(Structure):
        _fields_ = [
            ("selective_update",   c_uint32, 1),
            ("early_transport",    c_uint32, 1),
            ("crc_sel_update",     c_uint32, 1),
            ("y_gran_value",       c_uint16, 16),
            ('reserved',           c_uint32, 13)
        ]

    class SuRegions(Structure):
        _fields_ = [
            ("number_regions", c_uint32, 8),
            ("buffer_capacity", c_uint32, 8),
            ('reserved', c_uint32, 16)
        ]

    _fields_ = [
        ('flags', c_uint32),
        ('su_regions', c_uint32),
        ('reserved1', c_uint32, 4),
        ('color_bars', c_uint32, 4),
        ('chessboard', c_uint32, 4),
        ('solid_color', c_uint32, 4),
        ('solid_white', c_uint32, 4),
        ('solid_red', c_uint32, 4),
        ('solid_green', c_uint32, 4),
        ('solid_blue', c_uint32, 4),
        ('white_v_strips', c_uint32, 4),
        ('gradient_h_strips', c_uint32, 4),
        ('color_ramp', c_uint32, 4),
        ('color_square', c_uint32, 4),
        ('motion_pattern', c_uint32, 4),
        ('custom', c_uint32, 4),
        ('reserved2', c_uint32, 4),
        ('square_window', c_uint32, 4),
        ('dsc', c_uint32, 4)
    ]

    def color_bars_caps(self) -> PatternCaps:
        return PatternCaps(self.color_bars & 0x3)

    def chessboard_caps(self) -> PatternCaps:
        return PatternCaps(self.chessboard & 0x3)

    def solid_color_caps(self) -> PatternCaps:
        return PatternCaps(self.solid_color & 0x3)

    def solid_white_caps(self) -> PatternCaps:
        return PatternCaps(self.solid_white & 0x3)

    def solid_red_caps(self) -> PatternCaps:
        return PatternCaps(self.solid_red & 0x3)

    def solid_green_caps(self) -> PatternCaps:
        return PatternCaps(self.solid_green & 0x3)

    def white_v_strips_caps(self) -> PatternCaps:
        return PatternCaps(self.white_v_strips & 0x3)

    def gradient_h_strips_caps(self) -> PatternCaps:
        return PatternCaps(self.gradient_h_strips & 0x3)

    def color_ramp_caps(self) -> PatternCaps:
        return PatternCaps(self.color_ramp & 0x3)

    def color_square_caps(self) -> PatternCaps:
        return PatternCaps(self.color_square & 0x3)

    def motion_pattern_caps(self) -> PatternCaps:
        return PatternCaps(self.motion_pattern & 0x3)

    def custom_caps(self) -> PatternCaps:
        return PatternCaps(self.custom & 0x3)

    def square_window_caps(self) -> PatternCaps:
        return PatternCaps(self.square_window & 0x3)

    def dsc_caps(self) -> PatternCaps:
        return PatternCaps(self.dsc & 0x3)

    def calculate_size(self) -> int:
        return self.pr_su_regions().number_regions * self.pr_su_regions().buffer_capacity * 2 + 1

    def pr_flags(self) -> PRFlags:
        return self.PRFlags(self.flags & 0x1, (self.flags >> 1) & 0x1, (self.flags >> 2) & 0x1)

    def pr_su_regions(self) -> SuRegions:
        return self.SuRegions(self.su_regions & 0xFF, (self.su_regions >> 8) & 0xFF)


class PrStatus(Structure):
    _fields_ = [
        ("command_status", c_uint32, 8),
        ("status", c_uint32, 8),
        ('reserved', c_uint32, 8),
        ('error', c_uint32, 8)
    ]
