import dearpygui.dearpygui as dpg
import tifffile

from utils import *
from constants import SPACE, TREE_COLOR, ROAD_COLOR, BUILDING_COLOR
from remote_run import start_remote_execution, start_model_build, get_server_output_structure
from map_edit import dump_height_map, load_height_map, update_texture
from styles import get_accent_color, apply_theme
from generator import LCZ
from config import load_config, dump_config
from dynamic_ui import construct_config_ui, construct_model_output_structure_ui

def map_window_on_close_clb(s, a, u):
    delete_item_and_clear_alias(f'map_buildings_texture')
    delete_item_and_clear_alias(f'map_trees_texture')
    delete_item_and_clear_alias(f'map_roads_texture')
    delete_item_children_and_clear_aliases(f'map_drawlist')
    user_data = {
        'buildings_map': None,
        'trees_map': None,
        'roads_map': None,
        'height_map_file_path': None,
        'drawing': False,
        'prev_coords': None,
        'current_action': None,
        'max_height': 0,
        'output_dirs': None,
    }
    dpg.set_item_user_data('map_window', user_data)

def set_file_path_clb(s, a, u):
    file_path = a['file_path_name']
    dpg.set_value(u, file_path)

def construct_config_ui_clb(s, a, u):
    if not get_config_file_path():
        return
    delete_config_items_and_clear_aliases()
    update_config_values()
    construct_config_ui(get_config_file_path(), get_config())


################################################################################
#
#       Config
#
################################################################################


def update_config_values():
    config = get_config()
    for path in config:
        if dpg.does_item_exist(f'{get_config_file_path()}.{path}'):
            config[path].value = dpg.get_value(f'{get_config_file_path()}.{path}')
    set_main_window_value('config', config)

def config_save_as_clb(s, a, u):
    update_config_values()
    dump_config(get_config(), a['file_path_name'])
    dpg.show_item('message_popup')

def config_open_clb(s, a, u):
    delete_config_items_and_clear_aliases()
    config_file_path = a['file_path_name']
    config = load_config(config_file_path)
    set_main_window_value('config', config)
    set_main_window_value('config_file_path', config_file_path)
    construct_config_ui(a['file_path_name'], config)

def config_save_clb(s, a, u):
    update_config_values()
    dump_config(get_config(), get_config_file_path())
    dpg.show_item('message_popup')

def open_config_open_dialog_clb(s, a, u):
    dpg.show_item('config_open')

def show_config_search_window_clb(s, a, u):
    dpg.show_item('search_popup')

def open_config_save_as_dialog_clb(s, a, u):
    dpg.show_item('config_open')

################################################################################
#
#       Config Search
#
################################################################################


def search_clb(s, data, u):
    if not get_config_file_path():
        return

    if not data:
        return

    for path in get_config():
        if data.lower() in path.split('.')[-1]:
            dpg.set_y_scroll('main', dpg.get_item_pos('.'.join([get_config_file_path(), path.split('.')[0]]))[1])
            for tag in path_iter(path, prefix=get_config_file_path()):
                if dpg.get_value(COLLAPSING_HEADERS_UI) == True:
                    dpg.set_value(tag, True)
                else:
                    dpg.set_value(dpg.get_item_parent(dpg.get_item_parent(tag)), dpg.get_item_parent(tag))
            change_color_temporarily('.'.join([get_config_file_path(), path, 'text']), color=get_accent_color())


################################################################################
#
#       Map edit
#
################################################################################

def construct_map_layers(w, h):
    dpg.set_item_width('map_child_window', w)
    dpg.set_item_height('map_child_window', h)

    # dpg.add_texture_registry(tag='textures')
    dpg.add_dynamic_texture(w, h, np.zeros(w * h * 4), tag=f'map_buildings_texture', parent='textures')
    dpg.add_dynamic_texture(w, h, np.zeros(w * h * 4), tag=f'map_trees_texture', parent='textures')
    dpg.add_dynamic_texture(w, h, np.zeros(w * h * 4), tag=f'map_roads_texture', parent='textures')

    dpg.bind_item_theme('map_child_window', 'map_image_theme')
    dpg.add_drawlist(w, h, tag=f'map_drawlist', parent='map_child_window', pos=[0, 0])

    dpg.draw_image(f'map_buildings_texture', color=BUILDING_COLOR, tag=f'map_buildings_image', pmin=(0, 0), pmax=(w, h), parent=f'map_drawlist')
    dpg.draw_image(f'map_trees_texture', color=TREE_COLOR, tag=f'map_trees_image', pmin=(0, 0), pmax=(w, h), parent=f'map_drawlist')
    dpg.draw_image(f'map_roads_texture', color=ROAD_COLOR, tag=f'map_roads_image', pmin=(0, 0), pmax=(w, h), parent=f'map_drawlist')

def map_open_clb(s, a, u):
    height_map_file_path = a['file_path_name']

    if height_map_file_path.endswith('txt'):
        height_map = load_height_map(height_map_file_path)
        max_height = np.max(height_map)
        height_map /= max_height
    else:
        height_map = tifffile.imread(height_map_file_path)
        max_height = 1

    h, w = height_map.shape

    print(dpg.get_item_user_data('map_window'))

    set_map_window_value('buildings_map', height_map)
    set_map_window_value('roads_map', np.zeros((h, w)))
    set_map_window_value('trees_map', np.zeros((h, w)))
    set_map_window_value('height_map_file_path', height_map_file_path)
    set_map_window_value('max_height', max_height)

    construct_map_layers(w, h)
    
    update_texture()

    dpg.show_item('map_window')

def generate_map_clb(s, a, u):
    height_map = LCZ(config_path=f'configs/{s}.json').to_height_map(dtype=np.float64)

    max_height = np.max(height_map)
    height_map /= max_height

    h, w = height_map.shape

    set_map_window_value('buildings_map', height_map)
    set_map_window_value('roads_map', np.zeros((h, w)))
    set_map_window_value('trees_map', np.zeros((h, w)))
    set_map_window_value('height_map_file_path', f'{dpg.generate_uuid()}.txt')
    set_map_window_value('max_height', max_height)

    construct_map_layers(w, h)

    update_texture()

    dpg.show_item('map_window')

def save_map(file_path):
    if file_path.endswith('.tif') or file_path.endswith('.tiff'):
        with TiffWriter(file_path) as tif:
            tif.write(get_map_window_value('buildings_map'))
            tif.write(get_map_window_value('roads_map'))
            tif.write(get_map_window_value('trees_map'))
    else:
        dump_height_map(get_map_window_value('buildings_map'), file_path)

def map_save_clb(s, a, u):
    file_path = get_height_map_file_path()
    save_map(file_path)
    dpg.show_item('message_popup')

def map_save_as_clb(s, a, u):
    file_path = a['file_path_name']
    save_map(file_path)
    dpg.show_item('message_popup')

def open_map_save_as_dialog_clb(s, a, u):
    dpg.show_item('map_save_as')

def open_map_open_dialog_clb(s, a, u):
    dpg.show_item('map_open')

def set_action_clb(s, a, u):
    set_map_window_value('current_action', s)

def set_action_none_clb(s, a, u):
    set_map_window_value('current_action', None)


################################################################################
#
#       Styles
#
################################################################################


def apply_theme_clb(s, a, u):
    apply_theme(s)


################################################################################
#
#       Remote execution
#
################################################################################


def start_remote_execution_clb(s, a, u):
    dpg.configure_item('login_modal', show=False)
    u = dpg.get_item_user_data('login_modal')
    if u == 'build_model':
        start_model_build(dpg.get_value('server_username'), dpg.get_value('server_password'), dpg.get_value('gitlab_username'), dpg.get_value('gitlab_password'))
    elif u == 'run_on_lab_server':
        start_remote_execution(dpg.get_value('server_username'), dpg.get_value('server_password'))
    elif u == 'download_output':
        s = get_server_output_structure(dpg.get_value('server_username'), dpg.get_value('server_password'))
        folders, filepaths = parse_dirs(s)
        delete_item_children_and_clear_aliases('output')
        construct_model_output_structure_ui(filepaths, folders)
        dpg.show_item('model_output_window')

def build_model_on_lab_server_clb(s, a, u):
    pass

def show_get_credentials_modal_clb(s, a, u):
    dpg.set_item_user_data('login_modal', u)

    if u == 'run_on_lab_server':
        if not get_config_file_path():
            show_status_text('no config.txt specified. cannot run.')
            return

        update_config_values()
    
        dump_config(get_config(), 'tmp.txt')

        dpg.hide_item('gitlab_password') 
        dpg.hide_item('gitlab_username')

    elif u == 'download_output':
        dpg.hide_item('gitlab_password') 
        dpg.hide_item('gitlab_username')

    dpg.show_item('login_modal')