from UniTAP.libs.lib_uicl.uicl import *
from UniTAP.common import VideoMode, ColorInfo


class VideoFileFormat(IntEnum):
    UNKNOWN = -1
    BIN = 0
    MP4 = 1


class PictureFileFormat(IntEnum):
    UNKNOWN = -1
    BIN = 0
    BMP = 1
    PPM = 2
    DSC = 3


def uicl_cf_from_vm(color_format: ColorInfo.ColorFormat) -> UICL_Colorspace:
    if color_format == ColorInfo.ColorFormat.CF_RGB:
        return UICL_Colorspace.Colorspace_RGB
    elif color_format in [ColorInfo.ColorFormat.CF_YCbCr_444, ColorInfo.ColorFormat.CF_YCbCr_422,
                          ColorInfo.ColorFormat.CF_YCbCr_420]:
        return UICL_Colorspace.Colorspace_YCbCr
    else:
        return UICL_Colorspace.Colorspace_Unknown


def uicl_sampling_from_vm(color_format: ColorInfo.ColorFormat) -> UICL_Sampling:
    if color_format in [ColorInfo.ColorFormat.CF_RGB, ColorInfo.ColorFormat.CF_YCbCr_444]:
        return UICL_Sampling.Sampling_444
    elif color_format == ColorInfo.ColorFormat.CF_YCbCr_422:
        return UICL_Sampling.Sampling_422
    elif color_format == ColorInfo.ColorFormat.CF_YCbCr_420:
        return UICL_Sampling.Sampling_420
    else:
        return UICL_Sampling.Sampling_Unknown


def uicl_colorimetry_from_vm(colorimetry: ColorInfo.Colorimetry) -> UICL_Colorimetry:
    if colorimetry == ColorInfo.Colorimetry.CM_ITUR_BT601:
        return UICL_Colorimetry.Colorimetry_ITU_R_BT601
    elif colorimetry == ColorInfo.Colorimetry.CM_ITUR_BT709:
        return UICL_Colorimetry.Colorimetry_ITU_R_BT709
    elif colorimetry == ColorInfo.Colorimetry.CM_ITUR_BT2020_YCbCr:
        return UICL_Colorimetry.Colorimetry_ITU_R_BT2020
    else:
        return UICL_Colorimetry.Colorimetry_Unknown


def uicl_parameters_from_vm(vm: VideoMode):
    parameters = UICL_ImageParameters()

    parameters.Width = vm.timing.hactive
    parameters.Height = vm.timing.vactive
    parameters.BitsPerColor = vm.color_info.bpc
    parameters.Colorimetry = uicl_colorimetry_from_vm(vm.color_info.colorimetry)

    if vm.color_info.color_format == ColorInfo.ColorFormat.CF_RGB:
        parameters.Colorspace = UICL_Colorspace.Colorspace_RGB
        parameters.ComponentOrder = UICL_ComponentOrder.Order_RGB
        parameters.Sampling = UICL_Sampling.Sampling_444
        parameters.Packing = UICL_Packing.Packing_Packed
        parameters.Alignment = UICL_Alignment.Alignment_LSB
        parameters.IsFullRange = vm.color_info.DynamicRange == ColorInfo.DynamicRange.DR_VESA

    elif vm.color_info.color_format == ColorInfo.ColorFormat.CF_YCbCr_444:
        parameters.Colorspace = UICL_Colorspace.Colorspace_YCbCr
        parameters.ComponentOrder = UICL_ComponentOrder.Order_YCbCr
        parameters.Sampling = UICL_Sampling.Sampling_444
        parameters.Packing = UICL_Packing.Packing_Packed
        parameters.Alignment = UICL_Alignment.Alignment_LSB

        parameters.IsFullRange = False

    elif vm.color_info.color_format == ColorInfo.ColorFormat.CF_YCbCr_422:
        parameters.Colorspace = UICL_Colorspace.Colorspace_YCbCr
        parameters.ComponentOrder = UICL_ComponentOrder.Order_CbY0CrY1
        parameters.Sampling = UICL_Sampling.Sampling_422
        parameters.Packing = UICL_Packing.Packing_Packed
        parameters.Alignment = UICL_Alignment.Alignment_LSB

        parameters.IsFullRange = False

    elif vm.color_info.color_format == ColorInfo.ColorFormat.CF_YCbCr_420:
        parameters.Colorspace = UICL_Colorspace.Colorspace_YCbCr
        parameters.ComponentOrder = UICL_ComponentOrder.Order_YCbCr
        parameters.Sampling = UICL_Sampling.Sampling_420
        parameters.Packing = UICL_Packing.Packing_Planar
        parameters.Alignment = UICL_Alignment.Alignment_LSB

        parameters.IsFullRange = False

    return parameters


def uicl_image_from_vm_and_data(video_mode: VideoMode, data: bytearray) -> UICL_Image:
    image = UICL_Image()

    image.DataPtr = (c_uint8 * len(data))(*data)
    image.DataSize = len(data)
    image.Parameters = uicl_parameters_from_vm(video_mode)

    return image


def uicl_image_convert_to_vm(src_image: UICL_Image, video_mode: VideoMode) -> bytearray:
    dest_image = UICL_Image()

    dest_image.Parameters = uicl_parameters_from_vm(video_mode)
    result = UICL_GetRequiredBufferSize(dest_image)

    assert result >= UICL_SUCCESS, f"Calculation required buffer size failed with error {result}"

    dest_image.DataPtr = (c_uint8 * result)()
    dest_image.DataSize = result

    result = UICL_Convert(src_image, dest_image)

    assert result == UICL_SUCCESS, f"Image conversion failed with error {result}"

    return bytearray(dest_image.DataPtr[:dest_image.DataSize])
