#include "ubl-settings-events.h"

config main_config;

//functions

void on_save_start(main_window *widgets, char* path){
    gtk_spinner_start(GTK_SPINNER(widgets->LoadingSpinner));
    gtk_widget_show(widgets->LoadingSpinner);
    gtk_widget_hide(widgets->TabsBox);

    if (system(yon_debug_output("%s\n",config_presave_clean_command(path)))){};
}

void on_save_done(main_window *widgets, config_str output, int size){
    gtk_spinner_stop(GTK_SPINNER(widgets->LoadingSpinner));
    gtk_widget_hide(widgets->LoadingSpinner);
    gtk_widget_show(widgets->TabsBox);
	char *final_output = yon_char_parsed_to_string(output,size,"");
	if (final_output){
		printf("%s\n",final_output);
		free(final_output);
	}
	yon_char_parsed_free(output,size);
	textdomain(template_ui_LocaleName);
	switch (main_config.save_config){
		case YON_CONFIG_GLOBAL:
			yon_ubl_status_box_render(GLOBAL_SAVE_SUCCESS_LABEL,BACKGROUND_IMAGE_SUCCESS_TYPE);
			break;
		case YON_CONFIG_LOCAL:
			yon_ubl_status_box_render(LOCAL_SAVE_SUCCESS_LABEL,BACKGROUND_IMAGE_SUCCESS_TYPE);
			break;
		case YON_CONFIG_BOTH:
			yon_ubl_status_box_render(GLOBAL_LOCAL_SAVE_SUCCESS_LABEL,BACKGROUND_IMAGE_SUCCESS_TYPE);
			break;
	}
	textdomain(LocaleName);
	
}

void on_config_global_local_save(GtkWidget *, main_window *widgets){
    yon_interface_save(widgets);
    main_config.save_config=YON_CONFIG_BOTH;
    yon_save_proceed(NULL,YON_CONFIG_BOTH,config_get_global_command,NULL);
}

void on_config_local_save(GtkWidget *, main_window *widgets){
    yon_interface_save(widgets);
    main_config.save_config=YON_CONFIG_LOCAL;
    yon_save_proceed("system",YON_CONFIG_LOCAL,config_get_local_command,NULL);
    
}

void on_config_global_save(GtkWidget *, main_window *widgets){
    yon_interface_save(widgets);
    main_config.save_config=YON_CONFIG_GLOBAL;
    yon_save_proceed("global",YON_CONFIG_GLOBAL,config_get_global_command,NULL);
    
}

void on_config_custom_save(GtkWidget *, main_window *widgets){
    yon_interface_save(widgets);
    main_config.save_config=YON_CONFIG_LOCAL;
	template_saving_window *window = yon_save_proceed(NULL,YON_CONFIG_CUSTOM,config_get_command("system"),NULL);
	if (window){};
}

void on_config_local_load(GtkWidget *,main_window *widgets){
        yon_load_proceed(YON_CONFIG_LOCAL);
    g_thread_new("update_thread",(GThreadFunc)yon_interface_update,widgets);
	yon_ubl_status_box_render(yon_char_get_localised_from_lib(LOCAL_LOAD_SUCCESS_LABEL),BACKGROUND_IMAGE_SUCCESS_TYPE);
        main_config.load_mode=1;
}

void on_config_global_load(GtkWidget *,main_window *widgets){
        yon_load_proceed(YON_CONFIG_GLOBAL);
    g_thread_new("update_thread",(GThreadFunc)yon_interface_update,widgets);
	yon_ubl_status_box_render(yon_char_get_localised_from_lib(GLOBAL_LOAD_SUCCESS_LABEL),BACKGROUND_IMAGE_SUCCESS_TYPE);
        main_config.load_mode=0;
    
}

void on_config_custom_load(GtkWidget *,main_window *widgets){
	yon_load_proceed(YON_CONFIG_CUSTOM);
	yon_ubl_status_box_render(yon_char_get_localised_from_lib(GLOBAL_LOAD_SUCCESS_LABEL),BACKGROUND_IMAGE_SUCCESS_TYPE);
	main_config.load_mode=3;
    g_thread_new("update_thread",(GThreadFunc)yon_interface_update,widgets);
}

void yon_load_proceed(YON_CONFIG_TYPE type){
	if (type!=YON_CONFIG_CUSTOM){
		yon_config_clean();
	}
    if (!yon_char_is_empty(config_get_default_command))
        yon_config_load_config(YON_CONFIG_DEFAULT,config_get_default_command,NULL);
    switch (type){
        case YON_CONFIG_GLOBAL:
            yon_config_load_config(type,config_get_command("global"),NULL);
        yon_ubl_status_box_render(yon_char_get_localised_from_lib(GLOBAL_LOAD_SUCCESS_LABEL),BACKGROUND_IMAGE_SUCCESS_TYPE);
            break;
        case YON_CONFIG_LOCAL:
            yon_config_load_config(type,config_get_command("system"),NULL);
        yon_ubl_status_box_render(yon_char_get_localised_from_lib(LOCAL_LOAD_SUCCESS_LABEL),BACKGROUND_IMAGE_SUCCESS_TYPE);
            break;
        case YON_CONFIG_CUSTOM:
            char *path = NULL;
            path=yon_custom_config_init(GTK_FILE_CHOOSER_ACTION_OPEN);
            if (!yon_char_is_empty(path)){
                yon_config_clean();
                yon_config_load_config(type,config_get_command(path),NULL);
                yon_ubl_status_box_render(yon_char_get_localised_from_lib(LOCAL_LOAD_SUCCESS_LABEL),BACKGROUND_IMAGE_SUCCESS_TYPE);
            }
            break;
        default:
            break;
    }
}

void yon_interface_save(main_window *widgets){
    yon_config_clean();
    yon_menu_tables_save(widgets);
}

gboolean yon_list_clear(main_window *widgets){
    GList *list = gtk_container_get_children(GTK_CONTAINER(widgets->TabsBox));
    GList *iter = NULL;
    for (iter=list;iter;iter=iter->next){
        gtk_widget_destroy(GTK_WIDGET(iter->data));
    }
    g_hash_table_remove_all(main_config.trees);
    g_sequence_free(main_config.trees_order);
    main_config.trees=g_hash_table_new(g_str_hash,g_str_equal);
    main_config.trees_order=g_sequence_new(NULL);
    return G_SOURCE_REMOVE;
}

config_str yon_list_get(int *size){
    int config_size;
    config_str config_parameters = yon_config_get_all_by_key(AUDITD_search, &config_size);

    int current_size = 0;
    config_str current_parameters = NULL;

    if (config_size){
        current_size=config_size;
        current_parameters=config_parameters;
        for(int i=0;i<current_size;i++){
            char *id = yon_char_divide_search(current_parameters[i],"=",-1);
            free(yon_char_divide_search(id,"[",-1));
            yon_char_remove_last_symbol(id,']');
            if (strstr(current_parameters[i],"#")) {
                strstr(current_parameters[i],"#")[0]=';';
            } else {
                current_parameters[i] = yon_char_append(current_parameters[i],";");
            }
            char *tmp = yon_char_unite(id,";",current_parameters[i],NULL);
            free(current_parameters[i]);
            current_parameters[i]=tmp;
        }
    } else {
        int file_size;
        config_str file_lines = yon_resource_open_file(rules_path, &file_size);
        current_size=file_size;
        current_parameters=yon_char_parsed_rip(file_lines,&current_size,0);
    }

    (*size)=current_size;
    return current_parameters;    
}

void yon_list_resize(main_window *widgets){
    GList *list = g_hash_table_get_values(main_config.trees);
    GList *iter;
    int check_width=0;
    int key_width=0;
    int rule_width=0;
    for (iter = list;iter;iter=iter->next){
        gtk_widget_realize(((yon_menu_table*)iter->data)->EnabledCheck);
        gtk_widget_realize(((yon_menu_table*)iter->data)->IdLabel);
        gtk_widget_realize(((yon_menu_table*)iter->data)->RuleLabel);
        int temp_width = 0;
        gtk_widget_get_preferred_width(((yon_menu_table*)iter->data)->EnabledCheck,&temp_width,NULL);
        if (temp_width > check_width) check_width=temp_width;
        gtk_widget_get_preferred_width(((yon_menu_table*)iter->data)->IdLabel,&temp_width,NULL);
        if (temp_width > key_width) key_width=temp_width;
        gtk_widget_get_preferred_width(((yon_menu_table*)iter->data)->RuleLabel,&temp_width,NULL);
        if (temp_width > rule_width) rule_width=temp_width;
    }
    g_list_free(list);
    if (key_width||rule_width||check_width){
        list = g_hash_table_get_values(main_config.trees);
        for (iter = list;iter;iter=iter->next){
            if (gtk_widget_get_visible(((yon_menu_table*)iter->data)->IdLabel)){
                if (key_width)
                    gtk_widget_set_size_request(gtk_widget_get_parent(((yon_menu_table*)iter->data)->IdLabel),key_width,-1);
                if (check_width)
                    gtk_widget_set_size_request(gtk_widget_get_parent(((yon_menu_table*)iter->data)->EnabledCheck),check_width,-1);
                if (rule_width)
                    gtk_widget_set_size_request(gtk_widget_get_parent(((yon_menu_table*)iter->data)->RuleLabel),rule_width,-1);
            }
        }
        g_list_free(list);
        if (key_width) gtk_widget_set_size_request(widgets->CheckLevelBox,check_width,-1);
        if (key_width) gtk_widget_set_size_request(widgets->IDLabel,key_width,-1);
        if (rule_width) gtk_widget_set_size_request(widgets->RuleLabel,rule_width,-1);
    }
}

gboolean yon_list_init(build_data *data){
    gtk_spinner_start(GTK_SPINNER(data->widgets->LoadingSpinner));
    gtk_widget_show(data->widgets->LoadingSpinner);
    gtk_widget_hide(data->widgets->TabsBox);
    gtk_widget_set_sensitive(data->widgets->UpdateButton,0);
    yon_audit_status_update(data->widgets);
    main_config.comments_size=0;
    for (int i=0;i<data->current_size;i++){
        while(gtk_events_pending()) gtk_main_iteration();
        int parsed_size;
        config_str parsed = yon_char_parse(data->current_parameters[i],&parsed_size,";");

        char *key=NULL, *rule=NULL, *description=NULL;
        if (!yon_char_is_empty(parsed[0])&&parsed_size>0) {
            key = parsed[0];
        }

        if (!yon_char_is_empty(parsed[1])&&parsed_size>1){
            rule = parsed[1];

        }
        if (!yon_char_is_empty(parsed[2])&&parsed_size>2) {
                description = parsed[2];
        }
        

        // g_signal_connect(G_OBJECT(table->MainListBox),"row-selected",G_CALLBACK(on_selection_changed),table);

        yon_menu_table *table = yon_menu_table_row_insert(GTK_LIST_BOX(data->widgets->TabsBox),key,rule,description,NULL,data->widgets);

        gtk_widget_show(table->MainBox);

    }
    yon_list_resize(data->widgets);

    gtk_spinner_stop(GTK_SPINNER(data->widgets->LoadingSpinner));
    gtk_widget_hide(data->widgets->LoadingSpinner);
    gtk_widget_show(data->widgets->TabsBox);
    gtk_widget_set_sensitive(data->widgets->UpdateButton,1);
    return G_SOURCE_REMOVE;
}

void on_update_clicked(GtkWidget *, main_window *widgets){
    g_thread_new("update_thread",(GThreadFunc)yon_interface_update,widgets);

}

void *yon_interface_update(main_window *widgets){
    g_idle_add((GSourceFunc)yon_list_clear,widgets);

    int current_size = 0;
    config_str current_parameters = yon_list_get(&current_size);
    
    build_data *data = malloc(sizeof(build_data));
    data->widgets=widgets;
    data->current_parameters=current_parameters;
    data->current_size=current_size;
    g_idle_add((GSourceFunc)yon_list_init,data);


    return G_SOURCE_REMOVE;
}

gboolean on_selection_block(GtkWidget *, GdkEventButton *,main_window *){
    return 1;
}

gboolean on_selection_clean(GtkWidget *, GdkEventButton *event,main_window *widgets){
    if (event->button==1){
        gtk_list_box_unselect_all(GTK_LIST_BOX(widgets->TabsBox));
    }
    return 0;
}

void yon_audit_update(main_window *widgets){
    int size=0;
    config_str commands = yon_resource_open_file(commands_path,&size);
    int parsed_size;
    config_str parsed = yon_char_parse(commands[1],&parsed_size,";");
    int active_status = system(parsed[7]);
    // int enabled_status = system(parsed[8]);
    int suspend_status = WEXITSTATUS(system(parsed[11]));
    if (!active_status){
        if (suspend_status) {
            gtk_image_set_from_icon_name(GTK_IMAGE(widgets->AuditStatusImage),audit_paused_icon_path,GTK_ICON_SIZE_BUTTON);
        } else {
            gtk_image_set_from_icon_name(GTK_IMAGE(widgets->AuditStatusImage),audit_active_icon_path,GTK_ICON_SIZE_BUTTON);
        }   
    } else {
        gtk_image_set_from_icon_name(GTK_IMAGE(widgets->AuditStatusImage),audit_inactive_icon_path,GTK_ICON_SIZE_BUTTON);
    }
}

void on_active_changed(GtkWidget *, GdkEvent*,main_window *widgets){
    yon_audit_update(widgets);
    
}

void on_enabled_changed(GtkWidget *, GdkEvent*,main_window *widgets){
    yon_audit_update(widgets);
    
}

void on_audit_control(GtkWidget *, main_window *widgets){
    int size;
    config_str commands = yon_resource_open_file(commands_path,&size);
    int parsed_size;
    config_str parsed = yon_char_parse(commands[1],&parsed_size,";");

    service_window *window = yon_service_window_new("auditd.service",parsed[2],parsed[3],parsed[4],parsed[5],parsed[6],parsed[7],parsed[8]);
    g_signal_connect(G_OBJECT(window->ActiveImage),"notify::icon-name",G_CALLBACK(on_active_changed),widgets);
    g_signal_connect(G_OBJECT(window->EnableImage),"notify::icon-name",G_CALLBACK(on_enabled_changed),widgets);

    yon_gtk_window_setup(GTK_WINDOW(window->MainWindow),GTK_WINDOW(widgets->Window),_SERVICE_HEAD_LABEL("auditd.service"),icon_path,"service_window");
    yon_service_window_run(window);
    yon_audit_update(widgets);
}

void on_audit_start_clicked(GtkWidget *, service_window *window){
    int size;
    config_str commands = yon_resource_open_file(commands_path,&size);
    int parsed_size;
    config_str parsed = yon_char_parse(commands[1],&parsed_size,";");
    if (!system(parsed[10])){
        yon_ubl_status_box_spawn(GTK_CONTAINER(window->StatusBox),yon_char_get_localised_from_lib(SUCCESS_LABEL),5,BACKGROUND_IMAGE_SUCCESS_TYPE);
    } else {
        yon_ubl_status_box_spawn(GTK_CONTAINER(window->StatusBox),FAIL_LABEL,5,BACKGROUND_IMAGE_FAIL_TYPE);
    }
    yon_char_parsed_free(parsed,size);
    on_audit_update_clicked(NULL,window);
}

void on_audit_stop_clicked(GtkWidget *, service_window *window){
    int size;
    config_str commands = yon_resource_open_file(commands_path,&size);
    int parsed_size;
    config_str parsed = yon_char_parse(commands[1],&parsed_size,";");
    if (!system(parsed[9])){
        yon_ubl_status_box_spawn(GTK_CONTAINER(window->StatusBox),yon_char_get_localised_from_lib(SUCCESS_LABEL),5,BACKGROUND_IMAGE_SUCCESS_TYPE);
    } else {
        yon_ubl_status_box_spawn(GTK_CONTAINER(window->StatusBox),FAIL_LABEL,5,BACKGROUND_IMAGE_FAIL_TYPE);
    }
    yon_char_parsed_free(parsed,size);
    on_audit_update_clicked(NULL,window);
}

void on_audit_update_clicked(GtkWidget *, service_window *window){
    int status = WEXITSTATUS(system(check_audit_status_command));
    switch (status){
        case 0:{
            gtk_label_set_text(GTK_LABEL(window->ActiveLabel),ACTIVE_LABEL);
            gtk_image_set_from_icon_name(GTK_IMAGE(window->ActiveImage),service_start_status_icon_name,GTK_ICON_SIZE_BUTTON);
        } break;
        case 1: {
            gtk_label_set_text(GTK_LABEL(window->ActiveLabel),INACTIVE_LABEL);
            gtk_image_set_from_icon_name(GTK_IMAGE(window->ActiveImage),service_stop_status_icon_name,GTK_ICON_SIZE_BUTTON);
        } break;
        default:
            gtk_label_set_text(GTK_LABEL(window->ActiveLabel),PROTECTED_LABEL);
            gtk_image_set_from_icon_name(GTK_IMAGE(window->ActiveImage),service_start_status_icon_name,GTK_ICON_SIZE_BUTTON);

    }
}

void on_audit_configure(GtkWidget *, main_window *widgets){

    service_window *window = yon_service_window_new(SUBSYSTEM_CONFIGURATION_TITLE_LABEL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);

    g_signal_connect(G_OBJECT(window->StartButton),"clicked",G_CALLBACK(on_audit_start_clicked),window);
    g_signal_connect(G_OBJECT(window->StopButton),"clicked",G_CALLBACK(on_audit_stop_clicked),window);
    g_signal_connect(G_OBJECT(window->UpdateButton),"clicked",G_CALLBACK(on_audit_update_clicked),window);
    // g_signal_connect(G_OBJECT(window->EnableImage),"notify::icon-name",G_CALLBACK(on_enabled_changed),widgets);
    yon_gtk_window_setup(GTK_WINDOW(window->MainWindow),GTK_WINDOW(widgets->Window),TITLE_LABEL,icon_path,"service_window");
    gtk_button_clicked(GTK_BUTTON(window->UpdateButton));
    gtk_label_set_text(GTK_LABEL(window->HeadLabel),SUBSYSTEM_CONFIGURATION_TITLE_LABEL);
    gtk_label_set_text(GTK_LABEL(window->TitleLabel),AUDIT_SYSTEM_LABEL);

    gtk_widget_hide(window->EnableButton);
    gtk_widget_hide(window->DisableButton);
    gtk_widget_hide(window->RestartButton);
    gtk_widget_hide(window->StatusButton);
    gtk_widget_hide(gtk_widget_get_parent(window->EnableLabel));
    GtkWidget *label = gtk_label_new(AUDIT_WARNING_LABEL);
    gtk_box_pack_start(GTK_BOX(gtk_widget_get_parent(gtk_widget_get_parent(window->ActiveImage))),label,0,0,0);
    gtk_widget_show(label);
    yon_service_window_run(window);
    yon_audit_update(widgets);
}

void on_inspector_rules_update(GtkWidget *, inspector_window *window){
    yon_terminal_integrated_start(window->RulesTerminal,get_rules_command);    
}

void on_process_inspect_clicked(GtkWidget *,main_window *){
    GtkBuilder *builder = gtk_builder_new_from_resource(glade_path_insector);
    inspector_window *window = malloc(sizeof(inspector_window));
        
    window->MainWindow=yon_gtk_builder_get_widget(builder,"MainWindow");
    window->UpdateButton=yon_gtk_builder_get_widget(builder,"UpdateButton");
    window->RulesTerminal=yon_gtk_builder_get_widget(builder,"RulesTerminal");

    yon_terminal_integrated_start(window->RulesTerminal,get_rules_command);
    g_signal_connect(G_OBJECT(window->UpdateButton),"clicked", G_CALLBACK(on_inspector_rules_update),window);

    gtk_widget_show(window->MainWindow);
}

void on_move_up_clicked(GtkWidget *,main_window *widgets){
    GtkListBoxRow *row = gtk_list_box_get_selected_row(GTK_LIST_BOX(widgets->TabsBox));

    yon_menu_table *position = yon_menu_table_get_selected(row);
    if (position){
        int index = gtk_list_box_row_get_index(row)-1;
        GtkListBoxRow *prev_row = gtk_list_box_get_row_at_index(GTK_LIST_BOX(widgets->TabsBox),index);
        if (prev_row){
            yon_menu_table *prev = yon_menu_table_get_selected(prev_row);
            if (prev){
                g_sequence_move(position->order_position,prev->order_position);
                g_object_ref(G_OBJECT(position->MainBox));
                gtk_container_remove(GTK_CONTAINER(row),position->MainBox);
                gtk_widget_destroy(GTK_WIDGET(row));
                int index = gtk_list_box_row_get_index(prev_row);
                GtkWidget *row = gtk_list_box_row_new();
                gtk_widget_show(row);
                gtk_container_add(GTK_CONTAINER(row),position->MainBox);
                g_object_set_data(G_OBJECT(row),"menu_table",position);
                gtk_list_box_insert(GTK_LIST_BOX(widgets->TabsBox),row,index);

                gtk_list_box_select_row(GTK_LIST_BOX(widgets->TabsBox),gtk_list_box_get_row_at_index(GTK_LIST_BOX(widgets->TabsBox),index));
            }
        }
    }
}

void on_move_down_clicked(GtkWidget *,main_window *widgets){
    GtkListBoxRow *row = gtk_list_box_get_selected_row(GTK_LIST_BOX(widgets->TabsBox));

    yon_menu_table *position = yon_menu_table_get_selected(row);
    if (position){
        int index = gtk_list_box_row_get_index(row)+1;
        GtkListBoxRow *next_row = gtk_list_box_get_row_at_index(GTK_LIST_BOX(widgets->TabsBox),index);
        if (next_row){
            yon_menu_table *next = yon_menu_table_get_selected(next_row);
            if (next){
                g_sequence_move(position->order_position,next->order_position);
                g_object_ref(G_OBJECT(position->MainBox));
                gtk_container_remove(GTK_CONTAINER(row),position->MainBox);
                gtk_widget_destroy(GTK_WIDGET(row));
                int index = gtk_list_box_row_get_index(next_row)+1;
                GtkWidget *row = gtk_list_box_row_new();
                gtk_widget_show(row);
                gtk_container_add(GTK_CONTAINER(row),position->MainBox);
                g_object_set_data(G_OBJECT(row),"menu_table",position);
                gtk_list_box_insert(GTK_LIST_BOX(widgets->TabsBox),row,index);

                gtk_list_box_select_row(GTK_LIST_BOX(widgets->TabsBox),gtk_list_box_get_row_at_index(GTK_LIST_BOX(widgets->TabsBox),index));
            }
        }
    }
}

void on_audit_open_clicked(GtkWidget *,main_window *){
    char fk = fork();
    if (!fk){
        if (!access(audit_desktop_command,F_OK)){
            if (system(audit_desktop_command)){};
        } else if (!access(audit_local_command,F_OK)){
            if (system(audit_local_command)){};
        }
        exit(0);
    }
}

void on_selection_changed(GtkListBox *self, GtkListBoxRow *, main_window *widgets){
    int selection_state = !!gtk_list_box_get_selected_row(self);
        gtk_widget_set_sensitive(widgets->InsertAtButton,selection_state);
        gtk_widget_set_sensitive(widgets->RemoveButton,selection_state);
        gtk_widget_set_sensitive(widgets->MoveUpButton,selection_state);
        gtk_widget_set_sensitive(widgets->MoveDownButton,selection_state);
    
}

void yon_audit_status_update(main_window *widgets){
    int status = system(check_audit_status_command);
    if (!status){
        gtk_image_set_from_icon_name(GTK_IMAGE(widgets->AuditStatusImage),audit_active_icon_path,GTK_ICON_SIZE_BUTTON);
    } else {
        gtk_image_set_from_icon_name(GTK_IMAGE(widgets->AuditStatusImage),audit_inactive_icon_path,GTK_ICON_SIZE_BUTTON);
    }
}

void on_reset(GtkWidget *,main_window *widgets){
    dialog_confirmation_data *data = yon_confirmation_dialog_data_new();
    data->title=TITLE_LABEL;
    data->action_text=RESET_CONFIRMATION_LABEL;
    if (yon_confirmation_dialog_call(widgets->Window,data)==GTK_RESPONSE_ACCEPT){
        yon_list_clear(widgets);
    }
}

void on_template_refill(GtkWidget *,main_window *widgets){
    dialog_confirmation_data *data = yon_confirmation_dialog_data_new();
    data->title=TITLE_LABEL;
    data->action_text=REFILL_CONFIRMATION_LABEL;
    if (yon_confirmation_dialog_call(widgets->Window,data)!=GTK_RESPONSE_ACCEPT){
        return;
    }
    gtk_spinner_start(GTK_SPINNER(widgets->LoadingSpinner));
    gtk_widget_show(widgets->LoadingSpinner);
    gtk_widget_hide(widgets->TabsBox);
    gtk_widget_set_sensitive(widgets->UpdateButton,0);
    int current_size;
    config_str current_parameters = yon_resource_open_file(rules_path, &current_size);

    int comments = 0;
    for (int i=1;i<current_size;i++){
        while(gtk_events_pending()) gtk_main_iteration();
        int size;
        config_str parsed = yon_char_parse(current_parameters[i],&size,";");
        if (size){
            char *key = NULL;
            char *rule = NULL;
            char *description = NULL;

            if (!yon_char_is_empty(parsed[0])){
                key = yon_char_new(parsed[0]);
            } else {
                char *comment_id = yon_char_from_int(comments++);
                key = yon_char_append("comment_",comment_id);
            }
            if (size>1&&!yon_char_is_empty(parsed[0])){
                rule = parsed[1];
            }
            if (size>2&&!yon_char_is_empty(parsed[2])){
                description = g_markup_escape_text(parsed[2],strlen(parsed[2]));
            }
            yon_menu_table *table = g_hash_table_lookup(main_config.trees,key);
            if (table){
                table->key = key;
                table->rule = rule;
                table->description = description;
                yon_menu_table_update(table);

            } else {
                yon_menu_table_row_insert(GTK_LIST_BOX(widgets->TabsBox),key,rule,description,NULL,widgets);
            }
        }
    }

    gtk_spinner_stop(GTK_SPINNER(widgets->LoadingSpinner));
    gtk_widget_hide(widgets->LoadingSpinner);
    gtk_widget_show(widgets->TabsBox);
    gtk_widget_set_sensitive(widgets->UpdateButton,1);
}

void on_tabs_select_all(GtkWidget *, main_window *widgets){
    GList *children = gtk_container_get_children(GTK_CONTAINER(widgets->TabsBox));
    GList *iter;
    for (iter=children;iter;iter=iter->next){
        gtk_list_box_select_row(GTK_LIST_BOX(widgets->TabsBox),GTK_LIST_BOX_ROW(iter->data));
    }
    g_list_free(children);
}
void on_tabs_unselect_all(GtkWidget *, main_window *widgets){
    gtk_list_box_unselect_all(GTK_LIST_BOX(widgets->TabsBox));
}

void on_tabs_select(GtkWidget *, main_window *widgets){
    GtkListBoxRow *row = gtk_list_box_get_selected_row(GTK_LIST_BOX(widgets->TabsBox));
    if (!row) return;
    yon_menu_table *table = yon_menu_table_get_selected(row);
    if (!table) return;
    int active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(table->EnabledCheck));
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(table->EnabledCheck),!active);
}

void on_move_cursor (GtkListBox* self, GtkMovementStep object, gint p0, main_window *widgets){
    switch(object){
        case GTK_MOVEMENT_DISPLAY_LINES:{
            GtkListBoxRow *row = gtk_list_box_get_selected_row(self);
            int height;
            height = gtk_widget_get_allocated_height(GTK_WIDGET(row));
            gdouble scroll = gtk_adjustment_get_value(widgets->ScrollAdjustment);
            gtk_adjustment_set_value(widgets->ScrollAdjustment,scroll+(height*(gdouble)p0));
        } break;
        case GTK_MOVEMENT_PAGES:{

            gdouble height = gtk_adjustment_get_page_increment(widgets->ScrollAdjustment);
            gdouble scroll = gtk_adjustment_get_value(widgets->ScrollAdjustment);
            gtk_adjustment_set_value(widgets->ScrollAdjustment,scroll+((gdouble)height*(gdouble)p0));
            g_signal_stop_emission_by_name(self,"move-cursor");
        }
        break;
        default: break;
    }
}

void on_check_all_clicked(GtkWidget *,main_window *widgets){

    GList *children = gtk_container_get_children(GTK_CONTAINER(widgets->TabsBox));
    GList *iter;
    for (iter=children;iter;iter=iter->next){
        yon_menu_table *table = yon_menu_table_get_selected(GTK_LIST_BOX_ROW(iter->data));
        if (!table) continue;
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(table->EnabledCheck),1);
    }
    g_list_free(children);
}

void on_uncheck_all_clicked(GtkWidget *,main_window *widgets){
    GList *children = gtk_container_get_children(GTK_CONTAINER(widgets->TabsBox));
    GList *iter;
    for (iter=children;iter;iter=iter->next){
        yon_menu_table *table = yon_menu_table_get_selected(GTK_LIST_BOX_ROW(iter->data));
        if (!table) continue;
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(table->EnabledCheck),0);
    }

    g_list_free(children);
}

// standard functions

void config_init(){
    main_config.trees = g_hash_table_new(g_str_hash,g_str_equal);
    main_config.trees_order = g_sequence_new(NULL);
    main_config.comments_size=0;
}

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->UpdateButton = yon_gtk_builder_get_widget(builder,"UpdateButton");
    widgets->AuditPauseButton = yon_gtk_builder_get_widget(builder,"AuditPauseButton");
    widgets->AuditExitButton = yon_gtk_builder_get_widget(builder,"AuditExitButton");
    widgets->HeaderTree = yon_gtk_builder_get_widget(builder,"HeaderTree");
    widgets->ListRulesButton = yon_gtk_builder_get_widget(builder,"ListRulesButton");
    widgets->MoveUpButton = yon_gtk_builder_get_widget(builder,"MoveUpButton");
    widgets->MoveDownButton = yon_gtk_builder_get_widget(builder,"MoveDownButton");
    widgets->AddButton = yon_gtk_builder_get_widget(builder,"AddButton");
    widgets->InsertAtButton = yon_gtk_builder_get_widget(builder,"InsertAtButton");
    widgets->RemoveButton = yon_gtk_builder_get_widget(builder,"RemoveButton");
    widgets->ResetButton = yon_gtk_builder_get_widget(builder,"ResetButton");
    widgets->TemplateFillButton = yon_gtk_builder_get_widget(builder,"TemplateFillButton");
    widgets->StartAuditButton = yon_gtk_builder_get_widget(builder,"StartAuditButton");
    widgets->AuditStatusImage = yon_gtk_builder_get_widget(builder,"AuditStatusImage");
    widgets->TabsBox = yon_gtk_builder_get_widget(builder,"TabsBox");
    widgets->LoadingOverlay = yon_gtk_builder_get_widget(builder,"LoadingOverlay");
    widgets->LoadingSpinner = yon_gtk_builder_get_widget(builder,"LoadingSpinner");
    widgets->CheckLevelBox = yon_gtk_builder_get_widget(builder,"CheckLevelBox");
    widgets->IDLabel = yon_gtk_builder_get_widget(builder,"IDLabel");
    widgets->RuleLabel = yon_gtk_builder_get_widget(builder,"RuleLabel");
    widgets->DescriptionLabel = yon_gtk_builder_get_widget(builder,"DescriptionLabel");
    widgets->CheckAllButton = yon_gtk_builder_get_widget(builder,"CheckAllButton");
    widgets->UncheckAllButton = yon_gtk_builder_get_widget(builder,"UncheckAllButton");
    widgets->ScrollAdjustment = GTK_ADJUSTMENT(gtk_builder_get_object(builder,"ScrollAdjustment"));
    widgets->tables=NULL;

    main_config.IDSizeGroup = GTK_SIZE_GROUP(gtk_builder_get_object(builder,"IDSizeGroup"));
    main_config.RuleSizeGroup = GTK_SIZE_GROUP(gtk_builder_get_object(builder,"RuleSizeGroup"));
    main_config.DescriptionSizeGroup = GTK_SIZE_GROUP(gtk_builder_get_object(builder,"DescriptionSizeGroup"));
    }

    gtk_overlay_add_overlay(GTK_OVERLAY(widgets->LoadingOverlay),widgets->LoadingSpinner);
    /* 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->CheckAllButton),"clicked",G_CALLBACK(on_check_all_clicked),widgets);
    g_signal_connect(G_OBJECT(widgets->UncheckAllButton),"clicked",G_CALLBACK(on_uncheck_all_clicked),widgets);
    g_signal_connect(G_OBJECT(widgets->UpdateButton),"clicked",G_CALLBACK(on_update_clicked),widgets);
    g_signal_connect(G_OBJECT(widgets->AuditExitButton),"clicked",G_CALLBACK(on_audit_control),widgets);
    g_signal_connect(G_OBJECT(widgets->AuditPauseButton),"clicked",G_CALLBACK(on_audit_configure),widgets);
    g_signal_connect(G_OBJECT(widgets->ListRulesButton),"clicked",G_CALLBACK(on_process_inspect_clicked),widgets);
    g_signal_connect(G_OBJECT(widgets->MoveUpButton),"clicked",G_CALLBACK(on_move_up_clicked),widgets);
    g_signal_connect(G_OBJECT(widgets->MoveDownButton),"clicked",G_CALLBACK(on_move_down_clicked),widgets);
    g_signal_connect(G_OBJECT(widgets->AddButton),"clicked",G_CALLBACK(on_add_clicked),widgets);
    g_signal_connect(G_OBJECT(widgets->InsertAtButton),"clicked",G_CALLBACK(on_insert_clicked),widgets);    
    g_signal_connect(G_OBJECT(widgets->RemoveButton),"clicked",G_CALLBACK(on_remove_clicked),widgets);
    g_signal_connect(G_OBJECT(widgets->StartAuditButton),"clicked",G_CALLBACK(on_audit_open_clicked),widgets);
    g_signal_connect(G_OBJECT(widgets->ResetButton),"clicked",G_CALLBACK(on_reset),widgets);
    g_signal_connect(G_OBJECT(widgets->TemplateFillButton),"clicked",G_CALLBACK(on_template_refill),widgets);
    
    GtkAccelGroup *select_accelerator = gtk_accel_group_new();
    gtk_window_add_accel_group(GTK_WINDOW(widgets->Window),select_accelerator);
    gtk_widget_add_accelerator(widgets->TabsBox,"select-all",select_accelerator,GDK_KEY_a,GDK_CONTROL_MASK,GTK_ACCEL_VISIBLE);
    gtk_widget_add_accelerator(widgets->TabsBox,"unselect-all",select_accelerator,GDK_KEY_a,GDK_CONTROL_MASK | GDK_SHIFT_MASK,GTK_ACCEL_VISIBLE);
    gtk_widget_add_accelerator(widgets->TabsBox,"activate-cursor-row",select_accelerator,GDK_KEY_space,0,GTK_ACCEL_VISIBLE);
    g_signal_connect_after(G_OBJECT(widgets->AuditExitButton),"button-press-event",G_CALLBACK(on_selection_block),NULL);
    g_signal_connect_after(G_OBJECT(widgets->ListRulesButton),"button-press-event",G_CALLBACK(on_selection_block),NULL);
    g_signal_connect_after(G_OBJECT(widgets->MoveUpButton),"button-press-event",G_CALLBACK(on_selection_block),NULL);
    g_signal_connect_after(G_OBJECT(widgets->MoveDownButton),"button-press-event",G_CALLBACK(on_selection_block),NULL);
    g_signal_connect_after(G_OBJECT(widgets->AddButton),"button-press-event",G_CALLBACK(on_selection_block),NULL);
    g_signal_connect_after(G_OBJECT(widgets->RemoveButton),"button-press-event",G_CALLBACK(on_selection_block),NULL);
    g_signal_connect_after(G_OBJECT(widgets->StartAuditButton),"button-press-event",G_CALLBACK(on_selection_block),NULL);
    g_signal_connect(G_OBJECT(widgets->Window),"button-press-event",G_CALLBACK(on_selection_clean),widgets);

    g_signal_connect(G_OBJECT(widgets->TabsBox),"select-all",G_CALLBACK(on_tabs_select_all),widgets);
    g_signal_connect(G_OBJECT(widgets->TabsBox),"unselect-all",G_CALLBACK(on_tabs_unselect_all),widgets);
    g_signal_connect(G_OBJECT(widgets->TabsBox),"activate-cursor-row",G_CALLBACK(on_tabs_select),widgets);
    g_signal_connect(G_OBJECT(widgets->TabsBox),"move-cursor",G_CALLBACK(on_move_cursor),widgets);

		g_signal_connect(G_OBJECT(widgets->SaveMenuItem),"activate",G_CALLBACK(on_config_global_local_save),widgets);
		g_signal_connect(G_OBJECT(widgets->SaveGlobalMenuItem),"activate",G_CALLBACK(on_config_global_save),widgets);
		g_signal_connect(G_OBJECT(widgets->SaveLocalMenuItem),"activate",G_CALLBACK(on_config_local_save),widgets);
		g_signal_connect(G_OBJECT(widgets->SaveCustomMenuItem),"activate",G_CALLBACK(on_config_custom_save),widgets);
		g_signal_connect(G_OBJECT(widgets->LoadGlobalMenuItem),"activate",G_CALLBACK(on_config_global_load),widgets);
		g_signal_connect(G_OBJECT(widgets->LoadLocalMenuItem),"activate",G_CALLBACK(on_config_local_load),widgets);
		g_signal_connect(G_OBJECT(widgets->LoadCustomMenuItem),"activate",G_CALLBACK(on_config_custom_load),widgets);
		g_signal_connect(G_OBJECT(widgets->TabsBox),"row-selected",G_CALLBACK(on_selection_changed),widgets);
        gtk_widget_set_tooltip_markup(widgets->AuditExitButton,_SERVICE_HEAD_LABEL("auditd.service"));
    
    yon_rmb_menu_setup(widgets->TabsBox,NULL,NULL,ADD_TITLE_LABEL,add_icon_path,G_CALLBACK(on_add_clicked),widgets,REMOVE_TITLE_LABEL,remove_icon_path,G_CALLBACK(on_remove_clicked),widgets,NULL);

    yon_audit_update(widgets);
    yon_save_window_set_postsave_function(on_save_done,widgets);
    yon_save_window_set_presave_function(on_save_start,widgets);
    on_config_local_load(NULL,widgets);
    // g_thread_new("update_thread",(GThreadFunc)yon_interface_update,widgets);
}

int main(int argc, char *argv[]){
    setlocale(LC_ALL, "");
    textdomain (LocaleName);
    config_init();
    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_window_remove_exit_config_check(widgets);
    yon_root_button_setup((template_main_window*)widgets,argv,argc);

    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);
    main_config.launch_arguments=yon_char_parsed_copy(argv,argc);
    main_config.launch_size=argc;
    if (getuid()!=0){
        textdomain(template_ui_LocaleName);
        yon_ubl_status_box_render(ROOT_WARNING_LABEL,BACKGROUND_IMAGE_FAIL_TYPE);
        textdomain(LocaleName);
    }
    gtk_main();
    return 0;
}