import os.path
import subprocess
from typing import Union
from UniTAP.libs.lib_uicl.uicl_utils import *
from .dscl_api import *


def image_file_format_to_uicl_format(file_format):
    if file_format == ImageFileFormat.IFF_PPM:
        return UICL_ImageFileFormat.FILE_FORMAT_PPM
    elif file_format == ImageFileFormat.IFF_BIN:
        return UICL_ImageFileFormat.FILE_FORMAT_BIN
    elif file_format == ImageFileFormat.IFF_BMP:
        return UICL_ImageFileFormat.FILE_FORMAT_BMP
    else:
        raise TypeError(f"Incorrect file format: {file_format}")


def video_frame_to_rgb8(src_video_frame: VideoFrame, data_info: DataInfo) -> VideoFrame:
    rgb8_color_info = ColorInfo()
    rgb8_color_info.color_format = ColorInfo.ColorFormat.CF_RGB
    rgb8_color_info.bpc = 8
    rgb8_color_info.dynamic_range = ColorInfo.DynamicRange.DR_VESA

    return video_frame_to_ci(src_video_frame, rgb8_color_info, data_info)


def video_frame_to_ci(src_video_frame: VideoFrame, color_info: ColorInfo, data_info: DataInfo) -> VideoFrame:
    src_image = image_from_vf(src_video_frame)
    dst_image_params = image_params_from_size_and_ci(src_video_frame.width, src_video_frame.height,
                                                     color_info, data_info)

    if dst_image_params.Alignment != UICL_Alignment.Alignment_LSB:
        src_image = image_convert_to_parameters(src_image, dst_image_params)
    dst_image_params.Alignment = UICL_Alignment.Alignment_LSB

    return image_to_vf(image_convert_to_parameters(src_image, dst_image_params))


def video_frame_uicl_image(src_video_frame: VideoFrame, color_info: ColorInfo, data_info: DataInfo) -> UICL_Image:
    src_image = image_from_vf(src_video_frame)
    dst_image_params = image_params_from_size_and_ci(src_video_frame.width, src_video_frame.height,
                                                     color_info, data_info)

    if dst_image_params.Alignment != UICL_Alignment.Alignment_LSB:
        src_image = image_convert_to_parameters(src_image, dst_image_params)
    dst_image_params.Alignment = UICL_Alignment.Alignment_LSB
    return image_convert_to_parameters(src_image, dst_image_params)


def video_frame_save_to_file(video_frame: Union[VideoFrame, VideoFrameDSC], path: str, file_type: ImageFileFormat) -> bool:
    if file_type == ImageFileFormat.IFF_DSC:
        with open(path, "wb") as dsc_file:
            if b'DSCF' not in video_frame.data:
                dsc_file.write(b'DSCF')
            dsc_file.write(video_frame.data)
        return os.path.exists(path)
    else:
        if b'DSCF' not in video_frame.data:
            if video_frame.data_info.component_order == DataInfo.ComponentOrder.CO_UCDRX:
                data_info = DataInfo()
                color_info = ColorInfo()

                data_info.component_order = DataInfo.ComponentOrder.CO_RGB
                data_info.alignment = DataInfo.Alignment.A_LSB
                data_info.packing = DataInfo.Packing.P_PACKED
                color_info.color_format = ColorInfo.ColorFormat.CF_RGB
                color_info.bpc = 8
                color_info.dynamic_range = ColorInfo.DynamicRange.DR_VESA

                frame = video_frame_uicl_image(video_frame, color_info, data_info)
            else:
                frame = image_from_vf(video_frame)

            return image_save_to_file(frame, path, image_file_format_to_uicl_format(file_type))
        else:
            vf = decode_video_frame(video_frame)
            frame = image_from_vf(vf)
            return image_save_to_file(frame, path, image_file_format_to_uicl_format(file_type))


def calculate_crc(video_frame: VideoFrame) -> tuple:
    if not isinstance(video_frame, VideoFrame):
        raise TypeError("Calculate crc accept only VideoFrame object!")
    return uicl_image_calculate_crc(video_frame)
