import dearpygui.dearpygui as dpg
from datos.Config import ConfigManager
from logica.utilidades.Output import Output
import logica.utilidades.statics_feature as sf
import uuid
from log_register.Register import Register
import logica.utilidades.utils as ut
import numpy as np

config = ConfigManager()
output = Output("graphics")
registro = Register()

media = "0"

def registrar_datos(sender):
    # Register data
    texto = dpg.get_value("identifier")

    if texto == "":
        output.set_output("Record identifier not entered.")
        return
    
    if registro.exists_entry(texto):
        output.set_output("The record already exists.")
        return

    num_images = 0
    keypoints_data = {}
    # Register data
    if sf.exists_database(output):
        keypoints_data, num_images = sf.extract_id_and_keypoints(output)
        matches_data, num_images_matches = sf.extract_matches_entry(output)

    result = registro.create_entry(texto, num_images, keypoints_data, matches_data)
    
    if result == -1:
        output.set_output("Error registering data.")
        return
    
    leer_registros()
    dpg.configure_item("identifier", default_value="")
    
    output.set_output(result)

def registrar_datos_config(sender):
    # Register data
    texto = dpg.get_value("identifier_config")

    if texto == "":
        output.set_output("Configuration identifier not entered.")
        return
    
    if registro.exists_entry_config(texto):
        output.set_output("Configuration entry already exists.")
        return

    result = registro.create_config(texto)
    
    if result == -1:
        output.set_output("Error registering data.")
        return
    
    leer_registros_config()
    dpg.configure_item("identifier_config", default_value="")
    
    output.set_output(result)

def cargar_registro():
    global media
    # Load record
    identificador = dpg.get_value("combo_registro")
    if identificador == "":
        output.set_output("Record identifier not entered.")
        return -1
    
    result = registro.read_entry(identificador)

    if result == -1:
        output.set_output("Error loading record")
        return
    
    output.set_output("Data loaded successfully.")

def cargar_registro_config():

    # Load record
    identificador = dpg.get_value("combo_registro_config")
    if identificador == "":
        output.set_output("Configuration identifier not entered.")
        return -1
    
    result = registro.read_config_entry(identificador)

    if result == 0:
        output.set_output("Configuration set successfully")
        return
    
    output.set_output("Error loading record")


def seleccion_registro_callback():
    app_data = dpg.get_value("combo_registro")
    if app_data == "":
        output.set_output("Record not selected.")
        return
    
    generarGrafica(app_data)
    
    
def seleccion_registro_matches_callback():
    app_data = dpg.get_value("combo_registro")
    if app_data == "":
        output.set_output("Record not selected.")
        return
    
    generarMatchesGrafica(app_data)

def generarGrafica(dato):
    result = registro.read_entry(dato)
    if result == -1:
        output.set_output("Error loading data.")
        return 
    
    output.set_output("Generating Chart...")
    # Generate the chart
    generar_grafica_keypoints(result)

def generarMatchesGrafica(dato):
    result = registro.read_entry(dato)
    if result == -1:
        output.set_output("Error loading data.")
        return 
    
    output.set_output("Generating Chart...")
    # Generate the chart
    generar_grafica_matches(result, result.get_num_images())

def generar_grafica_keypoints(datos):
    global media
    # Generate the keypoints chart
    identifiers = [float(value) for value in datos.get_images().keys()]
    num_features = [float(value) for value in datos.get_images().values()]

    media, num_images = registro.get_media_keypoints(datos.get_identifier())

    dpg.set_value("media_keypoints", "Average keypoints per image: " + str(media))
    dpg.set_value("num_images", "Number of Images: " + str(num_images))

    tag_ventana = str(uuid.uuid4())
    axisY = str(uuid.uuid4())

    with dpg.window(label="Feature Chart per Image: " + datos.get_identifier(), tag=tag_ventana, width=500, height=500, show=True):
        dpg.add_text("Number of Features per Image:", parent=tag_ventana)

        # Create the line chart
        plot = dpg.add_plot(label="Features per Image", parent=tag_ventana, height=400, width=400)
        
        # Create axes
        dpg.add_plot_axis(dpg.mvXAxis, label="Image Identifier", parent=plot)
        dpg.add_plot_axis(dpg.mvYAxis, label="Number of Features", tag=axisY, parent=plot)
        
        # Create the data series
        dpg.add_line_series(identifiers, num_features, label="Number of Features", parent=axisY)

def generar_grafica_matches(datos, num_images):

    window_size = 1000

    # matches = {pair_id(id1,id2): num_matches}
    matches = datos.get_matches()

    modificado = {}
    for register in matches.keys():
        id1, id2 = sf.pair_id_to_image_ids(register)
        modificado[(id1, id2)] = matches[register]

    data_plot = np.zeros((num_images, num_images))

    for ids in modificado.keys():
        id1, id2 = ids

        data_plot[int(id1)-1][int(id2)-1] = int(modificado[(int(id1), int(id2))])
    
    data_plot_flat = data_plot.flatten().tolist()

    tag_ventana = str(uuid.uuid4())
    axisY = str(uuid.uuid4())

    with dpg.window(label="Images Match Chart: " + datos.get_identifier(), tag=tag_ventana, width=window_size, height=window_size, show=True):
        
        # Create the line chart
        plot = dpg.add_plot(label="Matches per pair of images", height=window_size*0.8, width=window_size*0.8, no_mouse_pos=True, parent=tag_ventana)
        # Create axes
        dpg.add_plot_axis(dpg.mvXAxis, label="Image 2", parent=plot)
        dpg.add_plot_axis(dpg.mvYAxis, label="Image 1", tag=axisY, parent=plot)
        
        # Create the data series
        dpg.add_heat_series(data_plot_flat, num_images, num_images, label="Number of Features", parent=axisY, scale_max=5000, scale_min=0, 
                            bounds_min=(0, 0), bounds_max=(num_images, num_images), format="%.0f")

def reset_config_callback():
    config.resetear_configuracion()
    output.set_output("Configuration reset successfully.")

def select_registro_callback():

    result, json = ut.seleccionar_json_callback(output)

    if result == 0:
        config.set_registro_folder(json)
        registro.append_config("REGISTRO_FOLDER", config.REGISTRO_FOLDER)

        dpg.configure_item("search_registro", default_value=json)

        # Set the JSON file of the record
        leer_registros()

def select_registro_config_callback():

    result, json = ut.seleccionar_json_callback(output)

    if result == 0:
        config.set_config_folder(json)
        registro.append_config("CONFIG_FOLDER", config.CONFIG_FOLDER)

        dpg.configure_item("search_config", default_value=json)

        # Set the JSON file of the record
        leer_registros_config()

def main_view(parent):
    # Initialize log view and texture controller
    output.main_view()
    num_images = 0

    items = registro.read_entries_identifiers()
    items_config = registro.read_config_identifiers()
    output.set_output("Records loaded successfully.")

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

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

    with dpg.group(horizontal=True, show=True, parent=grupo_general):
        dpg.add_combo(label="Select Entry", items=items, show=True, tag="combo_registro")

    dpg.add_input_text(label="New Entry Identifier", show=True, tag="identifier", parent=grupo_general)

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

    dpg.add_input_text(label="Source Record", show=True, default_value=registro.get_path(), enabled=False, tag="search_registro", parent=grupo_general)
    with dpg.group(horizontal=False, show=True, parent=grupo_general):
        
        dpg.add_button(label="Select Record", callback=select_registro_callback, show=True)

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

    dpg.add_text("Entry Options:", show=True, parent=grupo_general)
    with dpg.group(horizontal=True, show=True, parent=grupo_general):
        dpg.add_button(label="Register Entry", callback=registrar_datos, show=True)
        dpg.add_button(label="Delete Entry", callback=eliminar_registro, show=True)
        dpg.add_button(label="Read Entries", callback=leer_registros, show=True)

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

    dpg.add_text("Chart Options", show=True, parent=grupo_general)
    with dpg.group(horizontal=True, show=True, parent=grupo_general):
        dpg.add_button(label="Show Keypoints Chart", callback=seleccion_registro_callback, show=True)
        dpg.add_button(label="Show Matches HeatMap", callback=seleccion_registro_matches_callback, show=True)

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

    dpg.add_separator(show=True, parent=grupo_general)

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

    with dpg.group(horizontal=True, show=True, parent=grupo_general):
        dpg.add_combo(label="Select Config Entry", items=items_config, show=True, tag="combo_registro_config")

    dpg.add_input_text(label="New Config Identifier", show=True, tag="identifier_config", parent=grupo_general)

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

    dpg.add_input_text(label="Source Record Config", show=True, default_value=registro.get_path_config(), enabled=False, tag="search_config", parent=grupo_general)
    with dpg.group(horizontal=False, show=True, parent=grupo_general):
        
        dpg.add_button(label="Select Record", callback=select_registro_config_callback, show=True)

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

    dpg.add_text("Configuration Options", show=True, parent=grupo_general)
    with dpg.group(horizontal=True, show=True, parent=grupo_general):
        dpg.add_button(label="Register Config", callback=registrar_datos_config, show=True)
        dpg.add_button(label="Load Config Data", callback=cargar_registro_config, show=True)
        dpg.add_button(label="Delete Config", callback=eliminar_registro_config, show=True)
        dpg.add_button(label="Reset Configuration", callback=reset_config_callback, show=True)

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

    with dpg.group(horizontal=False, show=True, parent=grupo_general):
        dpg.add_text("Number of Images: " + str(num_images), show=True, parent=grupo_general, tag="num_images")
        dpg.add_text("Average Keypoints per Image: " + str(media), show=True, parent=grupo_general, tag="media_keypoints")


def leer_registros():
    lista = registro.read_entries_identifiers()
    dpg.configure_item("combo_registro", items=lista)

def leer_registros_config():
    lista = registro.read_config_identifiers()
    dpg.configure_item("combo_registro_config", items=lista)

def eliminar_registro():
    # Delete record
    texto = dpg.get_value("combo_registro")

    if texto == "":
        output.set_output("Record identifier not entered.")
        return
    result = registro.delete_entry(texto)
    dpg.configure_item("combo_registro", default_value="")

    leer_registros()

    return output.set_output(result)

def eliminar_registro_config():
    # Delete record
    texto = dpg.get_value("combo_registro_config")

    if texto == "":
        output.set_output("Configuration identifier not entered.")
        return
    
    result = registro.delete_entry_config(texto)

    items_config = registro.read_config_identifiers()
    dpg.configure_item("combo_registro_config", items=items_config)
    dpg.configure_item("combo_registro_config", default_value="")

    return output.set_output(result)

def hide_view():
    dpg.hide_item("graphics")
