#include "ubl-settings-keyboard.h"

config main_config;


gboolean yon_interface_update(main_window *widgets){
    g_signal_handlers_block_by_func(G_OBJECT(widgets->KeyboardModelCombo),G_CALLBACK(on_model_changed),widgets);
    g_signal_handlers_block_by_func(G_OBJECT(widgets->OptionsEditButton),G_CALLBACK(on_options_open),widgets);
    g_signal_handlers_block_by_func(G_OBJECT(widgets->NumLockCombo),G_CALLBACK(on_num_lock_changed),widgets);
    g_signal_handlers_block_by_func(G_OBJECT(widgets->LayoutChangingCombo),G_CALLBACK(on_options_save),widgets);
    g_signal_handlers_block_by_func(G_OBJECT(widgets->ScrollLockSwitch),G_CALLBACK(on_scroll_lock_switch),widgets);
    g_signal_handlers_block_by_func(G_OBJECT(widgets->ComposeSwitch),G_CALLBACK(on_compose_switch),widgets);
    g_signal_handlers_block_by_func(G_OBJECT(widgets->DefaultLayoutsSwitch),G_CALLBACK(on_layout_default_toggled),widgets);
    // g_signal_handlers_block_by_func(G_OBJECT(widgets->TTYLayoutCombo),G_CALLBACK(on_tty_changed),widgets);

    gtk_combo_box_set_active(GTK_COMBO_BOX(widgets->KeyboardModelCombo),0);
    gtk_combo_box_set_active(GTK_COMBO_BOX(widgets->NumLockCombo),0);
    {
        char *kbmodel = yon_config_get_by_key(model_parameter);
        if (kbmodel) {
            gtk_combo_box_set_active_id(GTK_COMBO_BOX(widgets->KeyboardModelCombo),kbmodel);
        } 
    }
    {
        gtk_list_store_clear(widgets->LayoutsList);
        char *layouts = config(keyboard_layout_parameter);

        int layouts_parsed_size;
        config_str layouts_parsed = yon_char_parse(layouts,&layouts_parsed_size,",");
        for(int i=0;i<layouts_parsed_size;i++){
            yon_layout_load(layouts_parsed[i],widgets);
        }
        if (yon_char_is_empty(layouts)||yon_config_check_ignore(keyboard_layout_parameter)){
            gtk_switch_set_active(GTK_SWITCH(widgets->DefaultLayoutsSwitch),1);
        } else {
            gtk_switch_set_active(GTK_SWITCH(widgets->DefaultLayoutsSwitch),0);
        }

        if (yon_char_is_empty(layouts)){
            char *element = yon_char_parsed_check_exist_begins_with(main_config.layouts_list,main_config.layouts_size,"us|");
            if (element){
                int parsed_size;
                config_str parsed = yon_char_parse(element,&parsed_size,"|");
                GtkTreeIter iter;
                gtk_list_store_append(widgets->LayoutsList,&iter);
                gtk_list_store_set(widgets->LayoutsList,&iter,0,parsed[0],2,_(parsed[1]),-1);
                yon_char_parsed_free(parsed,parsed_size);
            }
        }
    }
    {
        gtk_list_store_clear(widgets->OptionsList);
        char *options = config(options_parameter);
        if (!yon_char_is_empty(options)){
            GtkTreeIter iter;
            int size;
            config_str parsed = yon_char_parse(options,&size,",");
            if (!yon_char_is_empty(parsed[0])){
                gtk_combo_box_set_active_id(GTK_COMBO_BOX(widgets->LayoutChangingCombo),parsed[0]);
            } else {
                gtk_combo_box_set_active(GTK_COMBO_BOX(widgets->LayoutChangingCombo),0);
            }
            for (int i=1;i<size;i++){
                char *cur_string = (char*)g_hash_table_lookup(main_config.options,parsed[i]);
                if (yon_char_is_empty(cur_string)) continue;
                int option_parsed_size;
                config_str option_parsed = yon_char_parse(cur_string,&option_parsed_size,"|");

                gtk_list_store_append(widgets->OptionsList,&iter);
                gtk_list_store_set(widgets->OptionsList,&iter,0,option_parsed[0],1,_(option_parsed[1]),-1);
                yon_char_parsed_free(option_parsed,option_parsed_size);
            }
            if (yon_char_parsed_check_exist(parsed,size,"compose:rwin")>-1){
                gtk_switch_set_active(GTK_SWITCH(widgets->ComposeSwitch),1);
            } else {
                gtk_switch_set_active(GTK_SWITCH(widgets->ComposeSwitch),0);
            }
            if (yon_char_parsed_check_exist(parsed,size,"grp_led:scroll")>-1){
                gtk_switch_set_active(GTK_SWITCH(widgets->ScrollLockSwitch),1);
            } else {
                gtk_switch_set_active(GTK_SWITCH(widgets->ScrollLockSwitch),0);
            }

            yon_char_parsed_free(parsed,size);
        }
    }
    {
        char *name = yon_config_get_by_key(num_lock_boot_parameter);
        if (name) {
            if (!strcmp(name,"yes")) gtk_combo_box_set_active(GTK_COMBO_BOX(widgets->NumLockCombo),1);
            else if (!strcmp(name,"no")) gtk_combo_box_set_active(GTK_COMBO_BOX(widgets->NumLockCombo),2);
        }
    }

    {
        char *tty_layout = config(console_keymap_parameter);
        if (!yon_char_is_empty(tty_layout)){
            gtk_entry_set_text(GTK_ENTRY(widgets->TTYLayoutEntry),tty_layout);
        } else {
            gtk_entry_set_text(GTK_ENTRY(widgets->TTYLayoutEntry),yon_char_get_localised_from_lib(DEFAULT_LABEL));
        }

        char *tty_keymap = config(console_keymap_toggle_parameter);
        if (!yon_char_is_empty(tty_keymap)){
            gtk_entry_set_text(GTK_ENTRY(widgets->TTYSecondLayoutEntry),tty_keymap);
        } else {
            gtk_entry_set_text(GTK_ENTRY(widgets->TTYSecondLayoutEntry),yon_char_get_localised_from_lib(DEFAULT_LABEL));
        }
        
        char *tty_font = config(console_font_parameter);
        if (!yon_char_is_empty(tty_font)){
            gtk_entry_set_text(GTK_ENTRY(widgets->TTYFontEntry),tty_font);
        } else {
            gtk_entry_set_text(GTK_ENTRY(widgets->TTYFontEntry),yon_char_get_localised_from_lib(DEFAULT_LABEL));
        }
    }

    g_signal_handlers_unblock_by_func(G_OBJECT(widgets->KeyboardModelCombo),G_CALLBACK(on_model_changed),widgets);
    g_signal_handlers_unblock_by_func(G_OBJECT(widgets->OptionsEditButton),G_CALLBACK(on_options_open),widgets);
    g_signal_handlers_unblock_by_func(G_OBJECT(widgets->NumLockCombo),G_CALLBACK(on_num_lock_changed),widgets);
    g_signal_handlers_unblock_by_func(G_OBJECT(widgets->LayoutChangingCombo),G_CALLBACK(on_options_save),widgets);
    g_signal_handlers_unblock_by_func(G_OBJECT(widgets->ScrollLockSwitch),G_CALLBACK(on_scroll_lock_switch),widgets);
    g_signal_handlers_unblock_by_func(G_OBJECT(widgets->ComposeSwitch),G_CALLBACK(on_compose_switch),widgets);
    g_signal_handlers_unblock_by_func(G_OBJECT(widgets->DefaultLayoutsSwitch),G_CALLBACK(on_layout_default_toggled),widgets);
    // g_signal_handlers_unblock_by_func(G_OBJECT(widgets->TTYLayoutCombo),G_CALLBACK(on_tty_changed),widgets);
    return G_SOURCE_REMOVE;
}

void on_num_lock_changed(GtkComboBox *self, main_window *){
    switch (gtk_combo_box_get_active(self)){
        case 0:
            yon_config_remove_by_key(num_lock_boot_parameter);
            break;
        case 1:  yon_config_register(num_lock_boot_parameter,num_lock_boot_parameter_command,"yes");
            break;
        case 2:yon_config_register(num_lock_boot_parameter,num_lock_boot_parameter_command,"no");
            break;
    }
}

void on_model_changed(GtkComboBoxText *self, main_window *widgets){
    switch (gtk_combo_box_get_active(GTK_COMBO_BOX(self))){
        case 0:
            yon_config_remove_by_key(model_parameter);
            break;
        default: 
                char *id = (char*)gtk_combo_box_get_active_id(GTK_COMBO_BOX(widgets->KeyboardModelCombo));
                yon_config_register(model_parameter,model_parameter_command,id);
            break;
    }

}

void yon_config_init(){
    int size;
    main_config.models_list = gtk_list_store_new(3,G_TYPE_STRING,G_TYPE_STRING,G_TYPE_BOOLEAN);
    GtkTreeIter iter;

    main_config.layouts_store = gtk_tree_store_new(4,G_TYPE_STRING,G_TYPE_STRING,G_TYPE_STRING,G_TYPE_BOOLEAN);
    main_config.variants_list = yon_config_load(layouts_variant_command,&main_config.variants_size);
    main_config.layouts_list = yon_config_load(layouts_command,&main_config.layouts_size);
    for (int i=0;i<main_config.variants_size;i++){
        yon_char_remove_last_symbol(main_config.variants_list[i],'\n');
    }
    for (int i=0;i<main_config.layouts_size;i++){
        yon_char_remove_last_symbol(main_config.layouts_list[i],'\n');
    }

    {
        int size;
        config_str option_commands = yon_char_parsed_new(&size,
        lv2_options_command,
        lv3_options_command,
        ctrl_options_command,
        grp_led_options_command,
        mod_led_options_command,
        keypad_options_command,
        kpdl_options_command,
        caps_options_command,
        altwin_options_command,
        Compose_options_command,
        compat_options_command,
        currencysign_options_command,
        lv5_options_command,
        nbsp_options_command,
        japan_options_command,
        korean_options_command,
        esperanto_options_command,
        solaris_options_command,
        terminate_options_command,
        NULL);

        char *command_full = yon_char_parsed_to_string(option_commands,size,"; ");
        main_config.options = g_hash_table_new(g_str_hash,g_str_equal);
        int options_size;
        config_str options = yon_config_load(command_full,&options_size);
        for(int i=0;i<options_size;i++){
            yon_char_remove_last_symbol(options[i],'\n');
            int parsed_size;
            config_str parsed = yon_char_parse(options[i],&parsed_size,"|");
            g_hash_table_insert(main_config.options,yon_char_new(parsed[0]),yon_char_new(options[i]));
            yon_char_parsed_free(parsed,parsed_size);
        }
        free(command_full);
        yon_char_parsed_free(options,options_size);
        yon_char_parsed_free(option_commands,size);
    }

    main_config.options_list = gtk_list_store_new(3,G_TYPE_STRING,G_TYPE_STRING,G_TYPE_BOOLEAN);
    config_str rtn = yon_config_load(get_options_command,&size);
    for (int i=0; i<size;i++){
            yon_char_remove_last_symbol(rtn[i],'\n');
        int option_size;
        rtn[i] = yon_char_divide_search(rtn[i],"\n",-1);
        config_str option = yon_char_parse(rtn[i],&option_size,";");
        gtk_list_store_append(main_config.options_list,&iter);
        gtk_list_store_set(main_config.options_list,&iter,0,option[0],1,_(option[1]),-1);
    }
        yon_char_parsed_free(rtn,size);
}

void on_compose_switch(GtkWidget *,int status,main_window *widgets){
    switch(status){
        case 0:{
            yon_config_remove_element(options_parameter,"compose:rwin",",");
        } break;
        case 1:{
            yon_config_append_element(options_parameter,"compose:rwin",",");
        } break;
    }
    yon_interface_update(widgets);
}

void on_scroll_lock_switch(GtkWidget *,int status,main_window *widgets){
    switch(status){
        case 0:{
            yon_config_remove_element(options_parameter,"grp_led:scroll",",");
        } break;
        case 1:{
            yon_config_append_element(options_parameter,"grp_led:scroll",",");
        } break;
    }
    yon_interface_update(widgets);
}

void on_layout_default_sensitive_toggled(GtkWidget *, int status, main_window *widgets){
    gtk_widget_set_sensitive(widgets->LayoutTree,!status);
    gtk_widget_set_sensitive(widgets->LayoutAddButton,!status);
    if (status){
        gtk_widget_set_sensitive(widgets->LayoutRemoveButton,!status);
        gtk_widget_set_sensitive(widgets->LayoutMoveUpButton,!status);
        gtk_widget_set_sensitive(widgets->LayoutMoveDownButton,!status);
    }else {
        on_layout_selection_changed(GTK_TREE_VIEW(widgets->LayoutTree),widgets);

    }
}

void on_layout_default_toggled(GtkWidget *, int status, main_window *widgets){
    if (!status){
        GtkTreeModel *model = GTK_TREE_MODEL(widgets->LayoutsList);
        GtkTreeIter iter;
        char *locales = NULL;
        for_iter(model,&iter){
            char *target, *variant;

            gtk_tree_model_get(model,&iter,0,&target,1,&variant,-1);
            char *key = NULL;
            if (!yon_char_is_empty(variant)){
                key = yon_char_unite(target,"_",variant,NULL);
            } else {
                key = yon_char_new(target);
            }
            char *temp = yon_char_append_element(locales?locales:"",key,",");
            if (!yon_char_is_empty(locales)) free(locales);
            locales = temp;
        }
        if (!yon_char_is_empty(locales)){
            yon_config_register(keyboard_layout_parameter,keyboard_layout_parameter_command,locales);
        }
    }
}

void on_layout_selection_changed(GtkTreeView *self,main_window *widgets){
    int status = gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(self)),NULL,NULL);
        gtk_widget_set_sensitive(widgets->LayoutMoveDownButton,status);
        gtk_widget_set_sensitive(widgets->LayoutMoveUpButton,status);
        gtk_widget_set_sensitive(widgets->LayoutRemoveButton,status);

}

void on_option_selection_changed(GtkTreeView *self,main_window *widgets){
    int status = gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(self)),NULL,NULL);
        gtk_widget_set_sensitive(widgets->OptionsRemoveButton,status);

}

void yon_main_window_complete(main_window *widgets){ 
    widgets = yon_remalloc(widgets,sizeof(main_window)); 
    GtkBuilder *builder = gtk_builder_new_from_resource(glade_path); 
    gtk_box_pack_start(GTK_BOX(widgets->InterfaceBox),yon_gtk_builder_get_widget(builder,"BoxMain"),1,1,0); 
    // Custom widgets configuration 
    {

    widgets->KeyboardModelCombo = yon_gtk_builder_get_widget(builder,"KeyboardModelCombo");
    widgets->DefaultLayoutsSwitch = yon_gtk_builder_get_widget(builder,"DefaultLayoutsSwitch");
    widgets->LayoutTree = yon_gtk_builder_get_widget(builder,"LayoutTree");
    widgets->LayoutAddButton = yon_gtk_builder_get_widget(builder,"LayoutAddButton");
    widgets->LayoutRemoveButton = yon_gtk_builder_get_widget(builder,"LayoutRemoveButton");
    widgets->LayoutMoveUpButton = yon_gtk_builder_get_widget(builder,"LayoutMoveUpButton");
    widgets->LayoutMoveDownButton = yon_gtk_builder_get_widget(builder,"LayoutMoveDownButton");
    widgets->LayoutChangingCombo = yon_gtk_builder_get_widget(builder,"LayoutChangingCombo");
    widgets->OptionsTree = yon_gtk_builder_get_widget(builder,"OptionsTree");
    widgets->OptionsEditButton = yon_gtk_builder_get_widget(builder,"OptionsEditButton");
    widgets->OptionsRemoveButton = yon_gtk_builder_get_widget(builder,"OptionsRemoveButton");
    widgets->ComposeSwitch = yon_gtk_builder_get_widget(builder,"ComposeSwitch");
    widgets->ScrollLockSwitch = yon_gtk_builder_get_widget(builder,"ScrollLockSwitch");
    widgets->NumLockCombo = yon_gtk_builder_get_widget(builder,"NumLockCombo");

    widgets->TTYLayoutEntry = yon_gtk_builder_get_widget(builder,"TTYLayoutEntry");
    widgets->TTYLayoutButton = yon_gtk_builder_get_widget(builder,"TTYLayoutButton");
    widgets->TTYSecondLayoutEntry = yon_gtk_builder_get_widget(builder,"TTYSecondLayoutEntry");
    widgets->TTYSecondLayoutButton = yon_gtk_builder_get_widget(builder,"TTYSecondLayoutButton");
    widgets->TTYFontEntry = yon_gtk_builder_get_widget(builder,"TTYFontEntry");
    widgets->TTYFontButton = yon_gtk_builder_get_widget(builder,"TTYFontButton");
    widgets->LayoutsList = GTK_LIST_STORE(gtk_builder_get_object(builder,"LayoutsList"));
    widgets->OptionsList = GTK_LIST_STORE(gtk_builder_get_object(builder,"OptionsList"));

    /* Widget registration for config monitoring | Регистрация виджетов для мониторинга конфига */
    // yon_window_config_add_custom_parameter(widgets->HeadInfoLabel,"head-text","label",YON_TYPE_STRING); 

    /* Signal connection | Присоединение сигналов */

    g_signal_connect(G_OBJECT(widgets->LayoutAddButton),"clicked",G_CALLBACK(on_system_layouts_add),widgets);
    g_signal_connect(G_OBJECT(widgets->LayoutRemoveButton),"clicked",G_CALLBACK(on_system_layouts_remove),widgets);
    g_signal_connect(G_OBJECT(widgets->TTYLayoutButton),"clicked",G_CALLBACK(yon_keymaps_open),widgets);
    g_signal_connect(G_OBJECT(widgets->TTYSecondLayoutButton),"clicked",G_CALLBACK(yon_keymaps_open),widgets);
    g_signal_connect(G_OBJECT(widgets->TTYFontButton),"clicked",G_CALLBACK(yon_font_open),widgets);
    g_signal_connect(G_OBJECT(widgets->KeyboardModelCombo),"changed",G_CALLBACK(on_model_changed),widgets);
    g_signal_connect(G_OBJECT(widgets->OptionsEditButton),"clicked",G_CALLBACK(on_options_open),widgets);
    g_signal_connect(G_OBJECT(widgets->OptionsRemoveButton),"clicked",G_CALLBACK(on_option_remove),widgets);
    g_signal_connect(G_OBJECT(widgets->NumLockCombo),"changed",G_CALLBACK(on_num_lock_changed),widgets);
    g_signal_connect(G_OBJECT(widgets->LayoutChangingCombo),"changed",G_CALLBACK(on_options_save),widgets);
    g_signal_connect(G_OBJECT(widgets->ComposeSwitch),"state-set",G_CALLBACK(on_compose_switch),widgets);
    g_signal_connect(G_OBJECT(widgets->ScrollLockSwitch),"state-set",G_CALLBACK(on_scroll_lock_switch),widgets);
    // g_signal_connect(G_OBJECT(widgets->LayoutsList),"row-inserted",G_CALLBACK(on_layout_dnd_inserted),widgets);
    // g_signal_connect(G_OBJECT(widgets->LayoutsList),"row-deleted",G_CALLBACK(on_layout_dnd_deleted),widgets);

    g_signal_connect(G_OBJECT(widgets->LayoutTree),"cursor-changed",G_CALLBACK(on_layout_selection_changed),widgets);
    g_signal_connect(G_OBJECT(widgets->OptionsTree),"cursor-changed",G_CALLBACK(on_option_selection_changed),widgets);

    g_signal_connect(G_OBJECT(widgets->DefaultLayoutsSwitch),"state-set",G_CALLBACK(on_layout_default_toggled),widgets);
    g_signal_connect(G_OBJECT(widgets->DefaultLayoutsSwitch),"state-set",G_CALLBACK(on_layout_default_sensitive_toggled),widgets);

    g_signal_connect(G_OBJECT(widgets->LayoutMoveUpButton),"clicked",G_CALLBACK(on_layout_move_up),widgets);
    g_signal_connect(G_OBJECT(widgets->LayoutMoveDownButton),"clicked",G_CALLBACK(on_layout_move_down),widgets);

    g_signal_connect(G_OBJECT(widgets->LoadLocalMenuItem),"activate",G_CALLBACK(on_config_local_load),widgets);
    g_signal_connect(G_OBJECT(widgets->LoadGlobalMenuItem),"activate",G_CALLBACK(on_config_global_load),widgets);
    g_signal_connect(G_OBJECT(widgets->LoadCustomMenuItem),"activate",G_CALLBACK(on_config_custom_load),widgets);

    g_signal_connect(G_OBJECT(widgets->SaveMenuItem),"activate",G_CALLBACK(on_config_global_local_save),widgets);
    g_signal_connect(G_OBJECT(widgets->SaveLocalMenuItem),"activate",G_CALLBACK(on_config_local_save),widgets);
    g_signal_connect(G_OBJECT(widgets->SaveGlobalMenuItem),"activate",G_CALLBACK(on_config_global_save),widgets);
    g_signal_connect(G_OBJECT(widgets->SaveCustomMenuItem),"activate",G_CALLBACK(on_config_custom_save),widgets);
    yon_gtk_combo_box_block_scroll(GTK_COMBO_BOX(widgets->NumLockCombo));
    yon_gtk_combo_box_block_scroll(GTK_COMBO_BOX(widgets->KeyboardModelCombo));
    yon_gtk_combo_box_block_scroll(GTK_COMBO_BOX(widgets->LayoutChangingCombo));

    }
    
    int size;
    config_str models = yon_config_load(get_models_command,&size);
    for (int i=0;i<size;i++){
        yon_char_remove_last_symbol(models[i],'\n');
        int parsed_size;
        config_str parsed = yon_char_parse(models[i],&parsed_size,"|");
        gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(widgets->KeyboardModelCombo),parsed[0],_(parsed[1]));
        yon_char_parsed_free(parsed,parsed_size);
    }

    {
        int size;
        config_str options = yon_config_load(grp_options_command,&size);

        for (int i=0;i<size;i++){
            yon_char_remove_last_symbol(options[i],'\n');
            int parsed_size;
            config_str parsed = yon_char_parse(options[i],&parsed_size,"|");
            gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(widgets->LayoutChangingCombo),parsed[0],_(parsed[1]));
            yon_char_parsed_free(parsed,parsed_size);
        }
        yon_char_parsed_free(options,size);
    }
    yon_char_parsed_free(models,size);

    yon_root_button_setup((template_main_window*)widgets,main_config.launch_arguments,main_config.launch_size);
    yon_save_window_set_postsave_function(on_save_done,widgets);
    gtk_tree_view_column_clicked(GTK_TREE_VIEW_COLUMN(gtk_tree_view_get_column(GTK_TREE_VIEW(widgets->LayoutTree),0)));

    on_config_local_load(NULL,widgets);
}

int main(int argc, char *argv[]){ 
    setlocale(LC_ALL, "");
    textdomain (LocaleName);
    yon_config_init();
    main_config.launch_arguments=yon_char_parsed_copy(argv,argc);
    main_config.launch_size=argc;
    yon_ubl_connect_config((_template_config*)&main_config); 
    yon_ubl_window_init(TITLE_LABEL,TITLE_INFO_LABEL,LocaleName,CssPath,LocaleName,version_application,WIKI_LINK);
	config_str unfound = NULL;
	int size=0;
	yon_ubl_setup_arguments(argc,argv,&unfound,&size,NULL);
    gtk_init(&argc,&argv);
    template_main_window *widgets = yon_ubl_window_setup(); 

    yon_main_window_complete((main_window*)widgets);
    char *path = yon_char_unite(yon_ubl_user_get_home_directory(),"/.config/",LocaleName,"/",LocaleName,".conf",NULL);
    yon_window_config_load(path);
    if (getuid()!=0){
        yon_ubl_status_box_render(yon_char_get_localised_from_lib(ROOT_WARNING_LABEL),BACKGROUND_IMAGE_FAIL_TYPE);
    }
    gtk_main();
    return 0;
}