import os
from datos.Config import ConfigManager
import dearpygui.dearpygui as dpg
from log_register.Register import Register
import logica.controladores.image_preprocessing_controller as controlador

registro = Register()

config = ConfigManager()

resize_width = 0
resize_height = 0

is_updating = True

def select_image_folder_callback():
    result, folder = controlador.seleccionar_folder()
    if result == 0:
        config.set_images_folder(folder)
        dpg.configure_item("select_folder", default_value=config.IMAGES_FOLDER)
        registro.append_config("IMAGES_FOLDER", config.IMAGES_FOLDER)

def resize_images_callback():
    """
    Redimensiona todas las imágenes en la carpeta especificada.
    """
    if not config.is_images_folder_set():
        controlador.set_output("Please select an image folder.")
        return
    
    if not config.is_output_folder_set():
        controlador.set_output("Please select an output folder.")
        return

    width = dpg.get_value("width")
    height = dpg.get_value("height")

    if width == config.IMAGE_GLOBAL_WIDTH and height == config.IMAGE_GLOBAL_HEIGHT:
        controlador.set_output("No changes have been made.")
        return

    controlador.resize_images(width, height)

def delete_images_callback():
    """
    Elimina todas las imágenes en la carpeta especificada.
    """
    # Verificar si la carpeta existe
    output_path = config.get_output_folder()

    if not os.path.isdir(output_path):
        controlador.set_output("The specified folder does not exist.")
        return
    
    result = controlador.eliminar_imagenes(output_path)
    controlador.set_output(result)

def denoise_image(radius=2):
    """
    Elimina el ruido de una imagen utilizando un filtro de desenfoque.
    """
    if not config.is_images_folder_set():
        controlador.set_output("Please select an image folder.")
        return
    
    controlador.denoise_images(radius)

def update_data(sender):
    global is_updating
    
    if is_updating == False:
        dpg.configure_item("select_folder", default_value=config.IMAGES_FOLDER)
        dpg.configure_item("select_folder_output", default_value=config.DIR_OUTPUT)
        dpg.configure_item("work_folder", default_value=config.DIR_ACT)

        dpg.configure_item("brightness_factor", default_value=config.FACTOR_BRILLO)
        dpg.configure_item("contrast_factor", default_value=config.FACTOR_CONTRASTE)
        dpg.configure_item("color_factor", default_value=config.FACTOR_COLOR)

        dpg.configure_item("blurry_threshold", default_value=config.UMBRAL)
        dpg.configure_item("radius", default_value=config.REDUCCION_RUIDO)
        dpg.configure_item("noise_type", default_value=config.TIPO_RUIDO)
        dpg.configure_item("intensity", default_value=config.FACTOR_RUIDO)


        dpg.configure_item("width", default_value=config.IMAGE_GLOBAL_WIDTH)
        dpg.configure_item("height", default_value=config.IMAGE_GLOBAL_HEIGHT)

    if config.is_output_folder_set():
        tag = controlador.get_group_tag()
        result = dpg.get_item_configuration(tag)["show"]

        if not result:
            dpg.configure_item(tag, show=True)

def callback_brightness(sender):
    brightness_factor = dpg.get_value("brightness_factor")
    contrast_factor = dpg.get_value("contrast_factor")
    color_factor = dpg.get_value("color_factor")

    if brightness_factor == 1.0 and contrast_factor == 1.0 and color_factor == 1.0:
        controlador.set_output("No changes have been made.")
        return
    
    controlador.adjust_brightness_contrast(brightness_factor, contrast_factor, color_factor)

def callback_denoise_image(sender):
    if not config.is_images_folder_set():
        controlador.set_output("Please select an image folder.")
        return
    
    radius = dpg.get_value("radius")
    denoise_image(radius)

def mantener_ratio_callback(sender):
    if dpg.get_value("proporcion"):

        ratio = config.IMAGE_GLOBAL_WIDTH / config.IMAGE_GLOBAL_HEIGHT

        if sender == "width":
            width = dpg.get_value("width")
            # Calcula el nuevo valor del alto manteniendo el ratio
            height = int(width / ratio)

            dpg.set_value("height", height)

        elif sender == "height":
            height = dpg.get_value("height")
            # Calcula el nuevo valor del ancho manteniendo el ratio
            width = int(height * ratio)
            dpg.set_value("width", width)

    registro.append_config("IMAGE_GLOBAL_WIDTH", dpg.get_value("width"))
    registro.append_config("IMAGE_GLOBAL_HEIGHT", dpg.get_value("height"))

def remove_blurry_images():
    """
    Elimina las imágenes borrosas en una carpeta.
    """
    threshold = dpg.get_value("blurry_threshold")
    controlador.set_output("Removing blurry images...")
    
    controlador.remove_blurry_images(threshold)

    controlador.set_output("Blurry images removed.")
                
def callback_noise_image():
    """
    Agrega ruido a una imagen utilizando OpenCV.
    """
    noise_type = dpg.get_value("noise_type")
    intensity = dpg.get_value("intensity")

    controlador.add_noise_image(noise_type, intensity)

def reset_resolution_callback():
    dpg.set_value("width", config.IMAGE_GLOBAL_WIDTH)
    dpg.set_value("height", config.IMAGE_GLOBAL_HEIGHT)

    registro.append_config("IMAGE_GLOBAL_WIDTH", dpg.get_value("width"))
    registro.append_config("IMAGE_GLOBAL_HEIGHT", dpg.get_value("height"))

def select_image_folder_output_callback():
    result, folder = controlador.seleccionar_folder()
    if result == 0:
        config.set_output_folder(folder)
        dpg.configure_item("select_folder_output", default_value=config.DIR_OUTPUT)

        config.set_base_folder(folder)
        config.set_dir_database(folder)

        controlador.set_output(controlador.cargar_imagenes(folder))
        dpg.configure_item("width", default_value=config.IMAGE_GLOBAL_WIDTH)
        dpg.configure_item("height", default_value=config.IMAGE_GLOBAL_HEIGHT)
        
        registro.append_config("DIR_ACT", config.DIR_ACT)
        registro.append_config("DIR_OUTPUT", config.DIR_OUTPUT)
        registro.append_config("DIR_KEYPOINTS", config.DIR_KEYPOINTS)
        registro.append_config("DIR_MATCHES", config.DIR_MATCHES)

def delete_images_output_callback():
    """
    Elimina todas las imágenes en la carpeta especificada.
    """
    if not config.is_output_folder_set():
        controlador.set_output("Please select an image folder.")
        return
    # Verificar si la carpeta existe
    if not os.path.isdir(config.DIR_OUTPUT):
        controlador.set_output("The specified folder does not exist.")
        return
    
    result = controlador.eliminar_imagenes(config.DIR_OUTPUT)
    controlador.set_output(result)

def select_workfolder_callback():
    result, folder = controlador.seleccionar_folder()
    if result == 0:
        # Configuracion entorno de trabajo DIR_ACT y DIR_DATABASE
        config.set_base_folder(folder)
        config.set_dir_database(folder)
        dpg.configure_item("work_folder", default_value=config.DIR_ACT)

        registro.append_config("DIR_ACT", config.DIR_ACT)
        registro.append_config("DIR_DATABASE", config.DIR_DATABASE)
        registro.append_config("DIR_OUTPUT", config.DIR_OUTPUT)
        registro.append_config("DIR_KEYPOINTS", config.DIR_KEYPOINTS)
        registro.append_config("DIR_MATCHES", config.DIR_MATCHES)

def copy_images_to_output():
    controlador.copy_images_to_output()

    dpg.configure_item("width", default_value=config.IMAGE_GLOBAL_WIDTH)
    dpg.configure_item("height", default_value=config.IMAGE_GLOBAL_HEIGHT)

def main_view(parent):
    # Inicializar vista del log y el controlador de texturas
    controlador.init_main_view_output()

    grupo_general = dpg.add_group(parent=parent, tag="preprocessing", show=True)

    dpg.add_spacer(height=20, parent=grupo_general)

    dpg.add_input_text(label="Source Image Folder", show=True, default_value=config.IMAGES_FOLDER, enabled=False, tag="select_folder", parent=grupo_general)

    with dpg.group(horizontal=True, parent=grupo_general):
        dpg.add_button(label="Select Folder", show=True, callback=select_image_folder_callback)
        dpg.add_button(label="Delete Images", show=True, callback=delete_images_callback)

    dpg.add_spacer(height=10, parent=grupo_general)

    dpg.add_input_text(label="Output Image Folder", show=True, default_value=config.DIR_OUTPUT, enabled=False, tag="select_folder_output", parent=grupo_general)
    
    with dpg.group(horizontal=True, parent=grupo_general):
        dpg.add_button(label="Select Folder", show=True, callback=select_image_folder_output_callback)
        dpg.add_button(label="Delete Images", show=True, callback=delete_images_output_callback)

    with dpg.group(horizontal=False, show=True, parent=grupo_general):
        dpg.add_input_text(label="Work Folder", default_value=config.DIR_ACT, enabled=False, show=True, tag="work_folder")

        dpg.add_button(label="Change Work Folder", callback=select_workfolder_callback, show=True)

    dpg.add_spacer(height=10, parent=grupo_general)

    dpg.add_button(label="Copy Images to Output Folder", show=True, callback=copy_images_to_output, parent=grupo_general)

    dpg.add_spacer(height=15, parent=grupo_general)

    dpg.add_separator(show=True, parent=grupo_general)
        
    dpg.add_spacer(height=10, parent=grupo_general)

    with dpg.group(horizontal=False, show=True, parent=grupo_general):
        dpg.add_slider_int(label="Threshold", show=True, min_value=1, max_value=100, default_value=config.UMBRAL, tag="blurry_threshold", callback=callback_umbral)
        dpg.add_button(label="Remove Blurry Frames", show=True, callback=remove_blurry_images)

    dpg.add_spacer(height=10, parent=grupo_general)

    with dpg.group(horizontal=False, show=True, parent=grupo_general):
        dpg.add_text("Images Size", show=True)

        dpg.add_input_int(label="Width", show=True, default_value=config.IMAGE_GLOBAL_WIDTH, callback=mantener_ratio_callback, tag="width")
        dpg.add_input_int(label="Height", show=True, default_value=config.IMAGE_GLOBAL_HEIGHT, callback=mantener_ratio_callback, tag="height")

        dpg.add_checkbox(label="Maintain Aspect Ratio", show=True, tag="proporcion")
        with dpg.group(horizontal=True, show=True, parent=grupo_general):

            dpg.add_button(label="Resize", show=True, callback=resize_images_callback)
            dpg.add_button(label="Reset Size", show=True, callback=reset_resolution_callback)

    dpg.add_spacer(height=10, parent=grupo_general)

    with dpg.group(horizontal=False, show=True, parent=grupo_general):
        dpg.add_slider_float(label="Brightness Factor", min_value=0.1, max_value=2.0, default_value=config.FACTOR_BRILLO, tag="brightness_factor", show=True, callback=callback_bright)
        dpg.add_slider_float(label="Contrast Factor", min_value=0.1, max_value=2.0, default_value=config.FACTOR_CONTRASTE, tag="contrast_factor", show=True, callback=callback_contrast)
        dpg.add_slider_float(label="Color Factor", min_value=0.1, max_value=2.0, default_value=config.FACTOR_COLOR, tag="color_factor", show=True, callback=callback_color)
        dpg.add_button(label="Adjust", show=True, callback=callback_brightness)

    dpg.add_spacer(height=10, parent=grupo_general)

    with dpg.group(horizontal=False, show=True, parent=grupo_general):
        dpg.add_text("Noise Reduction:")
        dpg.add_slider_int(label="Radius", min_value=1, max_value=10, default_value=config.REDUCCION_RUIDO, tag="radius", show=True, callback=callback_radio)
        dpg.add_button(label="Remove Noise", show=True, callback=callback_denoise_image)

    dpg.add_spacer(height=10, parent=grupo_general)

    with dpg.group(horizontal=False, show=True, parent=grupo_general):
        dpg.add_combo(label="Noise Type", items=["Gaussian", "Salt and Pepper"], default_value=config.TIPO_RUIDO, tag="noise_type", show=True, callback=callback_tipo_ruido)
        dpg.add_slider_float(label="Intensity", min_value=0, max_value=1.0, default_value=config.FACTOR_RUIDO, tag="intensity", show=True, callback=callback_intensidad)
        dpg.add_button(label="Add Noise", show=True, callback=callback_noise_image)

    dpg.add_spacer(height=10, parent=grupo_general)

    with dpg.group(horizontal=False, show=True, tag="imagenes_procesadas_group", parent=grupo_general):
        dpg.add_text("Post-processed Images:", show=True)
        
        dpg.add_spacer(height=15, parent="imagenes_procesadas_group")

        with dpg.group(horizontal=True, show=True, tag="imagenes_group_procesing", parent=grupo_general):
            dpg.add_spacer(width=55, parent="imagenes_group_procesing")

    with dpg.item_handler_registry(show=False, tag="handler_preprocessing") as preprocessing_handler:
        dpg.add_item_visible_handler(callback=update_data)

    dpg.bind_item_handler_registry("preprocessing", "handler_preprocessing")

    init_texture_view()

def init_texture_view():
    controlador.init_texture_controller(config.DIR_OUTPUT)

def callback_bright(sender):
    registro.append_config("FACTOR_BRILLO", dpg.get_value(sender))

def callback_contrast(sender):
    registro.append_config("FACTOR_CONTRASTE", dpg.get_value(sender))

def callback_color(sender):
    registro.append_config("FACTOR_COLOR", dpg.get_value(sender))


def callback_umbral(sender):
    registro.append_config("UMBRAL", dpg.get_value(sender))

def callback_radio(sender):
    registro.append_config("REDUCCION_RUIDO", dpg.get_value(sender))

def callback_intensidad(sender):
    registro.append_config("FACTOR_RUIDO", dpg.get_value(sender))


def callback_tipo_ruido(sender):
    registro.append_config("TIPO_RUIDO", dpg.get_value(sender))

def show_view():
    global is_updating
    is_updating = False

    update_data(None)
    is_updating = True
    
    dpg.show_item("preprocessing")