from ctypes import Structure, c_uint32, c_uint64
from enum import IntEnum
from typing import Union
from .types import ASParams, ConstantASParams, PGAdaptiveSyncPatternType, SquareASParams, ZigzagASParams, FixedASParams
from .pg_pattern_params import PGPatternParams, PGScrollingParams, SolidColorParams, WhiteVStripsParams, \
    GradientStripsParams, MotionParams, SquareWindowParams, StepsScrollingParams


class PGPatternID(IntEnum):
    Disabled = 0
    ColorBars = 1
    Chessboard = 2
    SolidColor = 3
    SolidWhite = 4
    SolidRed = 5
    SolidGreen = 6
    SolidBlue = 7
    WhiteVStrips = 8
    GradientRGBStripes = 9
    ColorRamp = 10
    ColorSquares = 11
    Motion_Pattern = 12
    ImageFile = 13
    Playback = 14
    SquareWindow = 15
    DscImage = 16


class PGPatternType(IntEnum):
    FPGA = 0
    NIOS = 1
    Image = 2
    Scalable = 3
    VTG = 4
    Software = 5


class PgCaps(Structure):
    class PgCapsFlags(Structure):
        _fields_ = [
            ("custom_vp", c_uint32, 1),
            ("playback_vp", c_uint32, 1),
            ("vrr_supported", c_uint32, 1),
            ("color_modes_for_non_fw_pattern", c_uint32, 1),
            ("cea_vesa_dynamic_range", c_uint32, 1),
            ("dsc_supported", c_uint32, 1),
            ("high_dynamic_range", c_uint32, 1),
            ("adaptive_sync", c_uint32, 1),
            ("scrolling_pattern", c_uint32, 1),
            ("panel_replay", c_uint32, 1),
            ("alpm", c_uint32, 1),
            ("raw_y_only", c_uint32, 1),
            ("psr", c_uint32, 1),
            ('reserved', c_uint32, 19)
        ]

    _fields_ = [
        ('max_h_active', c_uint32),
        ('max_v_active', c_uint32),
        ('max_frame', c_uint32),
        ('flags', PgCapsFlags),
        ('max_h_total', c_uint32),
        ('max_v_total', c_uint32),
        ('max_pix_rate', c_uint64),
        ('patterns', c_uint32)
    ]


class CustomTimingFlags(Structure):
    _fields_ = [
        ('color_depth', c_uint32, 8),
        ('interlace', c_uint32, 1),
        ('h_sync_polarity', c_uint32, 1),
        ('v_sync_polarity', c_uint32, 1),
        ('color_space', c_uint32, 4),
        ('', c_uint32, 1),
        ('colorimetry', c_uint32, 4),
        ('', c_uint32, 10),
        ('dynamic_range', c_uint32, 1)
    ]


def get_as_params_value(params: ASParams) -> list:
    if isinstance(params, ConstantASParams):
        return [PGAdaptiveSyncPatternType.AS_Constant.value, params.lines]
    elif isinstance(params, SquareASParams):
        return [PGAdaptiveSyncPatternType.AS_Square.value, params.min_lanes, params.max_lanes, params.period_frames]
    elif isinstance(params, ZigzagASParams):
        return [PGAdaptiveSyncPatternType.AS_Zigzag.value, params.min_lanes, params.max_lanes, params.increase_lines,
                params.decrease_lines]
    elif isinstance(params, FixedASParams):
        return [PGAdaptiveSyncPatternType.AS_Fixed.value, params.refresh_rate, params.divide_by_1_001,
                params.increase_lines, params.decrease_lines]


def get_pattern_params_value(params: Union[PGPatternParams, PGScrollingParams], bpc: int = 8) -> list:
    if isinstance(params, SolidColorParams):
        up_shift = 16 - bpc
        return [(((params.first << up_shift) << 16) | (params.second << up_shift)), (params.third << up_shift)]
    elif isinstance(params, WhiteVStripsParams):
        return [params.white_stripes_width, params.black_stripes_width]
    elif isinstance(params, GradientStripsParams):
        return [params.color_step]
    elif isinstance(params, MotionParams):
        return [params.frames_count]
    elif isinstance(params, SquareWindowParams):
        return [params.white_square]
    elif isinstance(params, StepsScrollingParams):
        return [params.frames, params.horizontally, params.frames, params.vertically]
