#include "ubinstall-gtk.h"

// void on_os_components_uncheck_all(GtkWidget *,main_window *widgets){
//     int active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widgets->OSSoftwareUncheckAllCheck));
//     switch(active){
//         case 1:{
//             GList *list = gtk_container_get_children(GTK_CONTAINER(widgets->OSSoftwareListBox));
//             GList *iter;
//             for(iter = list;iter;iter=iter->next){
//                 os_row *row = g_object_get_data(iter->data,"kernel_row");
//                 int sensitive = gtk_widget_get_sensitive(row->InstallCheck);
//                 if (sensitive){
//                     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(row->InstallCheck),0);
//                 }
//             }
//         } break;
//     }
//     gtk_widget_hide(widgets->OSSoftwareUncheckAllCheck);
//     g_signal_handlers_block_by_func(G_OBJECT(widgets->OSSoftwareUncheckAllCheck),on_os_components_uncheck_all,widgets);
//     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widgets->OSSoftwareUncheckAllCheck),0);
//     g_signal_handlers_unblock_by_func(G_OBJECT(widgets->OSSoftwareUncheckAllCheck),on_os_components_uncheck_all,widgets);
// }

void on_os_components_switch_all(GtkWidget *self,main_window *widgets){
    g_signal_handlers_block_by_func(G_OBJECT(self),G_CALLBACK(on_os_components_switch_all),widgets);
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(self),0);
    g_signal_handlers_unblock_by_func(G_OBJECT(self),G_CALLBACK(on_os_components_switch_all),widgets);
    int active = !!g_object_get_data(G_OBJECT(self),"uncheck");
    GList *list = gtk_container_get_children(GTK_CONTAINER(widgets->OSSoftwareListBox));
    GList *iter;
    for(iter = list;iter;iter=iter->next){
        os_row *row = g_object_get_data(iter->data,"kernel_row");
        int sensitive = gtk_widget_get_sensitive(row->InstallCheck);
        if (sensitive){
            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(row->InstallCheck),!active);
        }
    }
    switch(active){
            case 0: gtk_button_set_label(GTK_BUTTON(self),UNCHECK_ALL_LABEL);
            g_object_set_data(G_OBJECT(self),"uncheck",widgets);
            break;
            case 1: gtk_button_set_label(GTK_BUTTON(self),CHECK_ALL_LABEL);
            g_object_set_data(G_OBJECT(self),"uncheck",NULL);
    }
}

int yon_os_components_check_packages_size(GtkWidget *, main_window *widgets){
        long pacman_size = 0;
    {
        int active = 1;
        GList *list = gtk_container_get_children(GTK_CONTAINER(widgets->OSSoftwareListBox));
        GList *listiter;
        for (listiter=list;listiter;listiter=listiter->next){
            os_row *row = g_object_get_data(G_OBJECT(listiter->data),"kernel_row");
            if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(row->InstallCheck))){
                long cur_size = row->size_raw;
                pacman_size += cur_size;
                if (gtk_widget_get_sensitive(row->InstallCheck)){
                    // gtk_widget_show(widgets->OSSoftwareUncheckAllCheck);
                    active = 0;
                }
            }
        }
        switch(active){
            case 0: gtk_button_set_label(GTK_BUTTON(widgets->OSSoftwareUncheckAllCheck),UNCHECK_ALL_LABEL);
            g_object_set_data(G_OBJECT(widgets->OSSoftwareUncheckAllCheck),"uncheck",widgets);
            break;
            case 1: gtk_button_set_label(GTK_BUTTON(widgets->OSSoftwareUncheckAllCheck),CHECK_ALL_LABEL);
            g_object_set_data(G_OBJECT(widgets->OSSoftwareUncheckAllCheck),"uncheck",NULL);
        }
    }
    {
        GtkTreeIter iter;
        GtkTreeModel *model = GTK_TREE_MODEL(widgets->PacmanSoftwareChosenList);
        for_iter(model, &iter){
            char *name;
            gtk_tree_model_get(model,&iter,1,&name,-1);
            long size = yon_packages_get_installed_size(YON_PACKAGES_ALL,name);
            pacman_size+=size;
        }
        char *overall_str = NULL;
        if (pacman_size){
            overall_str = yon_size_long_convert_automatic_to_string(pacman_size);
        } else {
            overall_str = yon_char_unite("0 ",yon_size_get_name_from_letter('K'),NULL);
        }
        gtk_label_set_text(GTK_LABEL(widgets->OSComponentsOverallSizeLabel),overall_str);
        if (!yon_char_is_empty(overall_str)) free(overall_str);
    }
    
    return 1;
}

int yon_os_components_save(main_window *widgets){
    if (!yon_installation_check_packages_size(widgets)) return 0;
    
    GList *list = gtk_container_get_children(GTK_CONTAINER(widgets->OSSoftwareListBox));
    GList *iter;
    int size=0;
    int overall_num=0;
    config_str modules = NULL;
    for(iter = list;iter;iter=iter->next){
        os_row *row = g_object_get_data(iter->data,"kernel_row");
        char *target = row->source;
        int status = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(row->InstallCheck));
        if (status){
            yon_char_parsed_add_or_create_if_exists(modules,&size,target);
        }
        overall_num++;
    }
    g_list_free(list);
    if (size&&size==overall_num){
        yon_config_register(modules_parameter,modules_parameter_command,"auto");
    } else if (size){
        char *final = yon_char_parsed_to_string(modules,size,",");
        yon_config_register(modules_parameter,modules_parameter_command,final);
    } else {
        yon_config_register(modules_parameter,modules_parameter_command,"none");
        if(main_config.configure_mode)
            yon_ubl_status_box_spawn(GTK_CONTAINER(widgets->StatusBox),MAIN_COMPONENTS_ALL_SELECTED_LABEL,5,BACKGROUND_IMAGE_INFO_TYPE);
        else
            yon_ubl_status_box_spawn(GTK_CONTAINER(widgets->StatusBox),NOTHING_CHOSEN_LABEL,5,BACKGROUND_IMAGE_INFO_TYPE);
        yon_ubl_status_highlight_incorrect(widgets->OSSoftwareListBox);
    }
    if (!main_config.configure_mode){
        int size;
        config_str parameters = yon_config_get_save_parameters_by_key(&size,modules_parameter,NULL);
        if (parameters){
            char *command_parameters = yon_char_parsed_to_string(parameters,size," -- ");
            char *command = yon_char_unite(ubconfig_dull_command,"--target system ",command_parameters,NULL);
            if (!system(yon_debug_output("%s\n",command))){}
            free(command);
            yon_char_parsed_free(parameters,size);
        }
    }
    return 1;
}

gboolean on_os_components_info(GtkWidget *, GdkEventButton *, os_row *row){
    yon_package_info_window_create(row->modules);
    return 1;
}

os_row *yon_os_row_new(){
    os_row *row = new(os_row);
    memset(row,0,sizeof(os_row));
    GtkBuilder *builder = gtk_builder_new_from_resource(glade_path_os_row);
    row->RowBox = yon_gtk_builder_get_widget(builder,"TableRow");
    row->InstallCheck = yon_gtk_builder_get_widget(builder,"InstallCheck");
    row->NameLabel = yon_gtk_builder_get_widget(builder,"NameLabel");
    row->RowOverlay = yon_gtk_builder_get_widget(builder,"RowOverlay");
    row->TagsBox = yon_gtk_builder_get_widget(builder,"TagsBox");
    row->VersionLabel = yon_gtk_builder_get_widget(builder,"VersionLabel");
    row->DescriptionLabel = yon_gtk_builder_get_widget(builder,"DescriptionLabel");
    row->SourceLabel = yon_gtk_builder_get_widget(builder,"SourceLabel");
    row->SizeLabel = yon_gtk_builder_get_widget(builder,"SizeLabel");
    row->name=NULL;
    row->modules=NULL;
    row->version=NULL;
    row->size_raw=0;

    gtk_overlay_add_overlay(GTK_OVERLAY(row->RowOverlay),row->NameLabel);
    g_signal_connect(G_OBJECT(row->NameLabel),"activate-link",G_CALLBACK(on_os_components_info),row);
    row->row = yon_gtk_builder_get_widget(builder,"MainRow");
    gtk_widget_show(row->row);
    g_object_set_data(G_OBJECT(row->InstallCheck),"kernel_row",row);
    g_object_set_data(G_OBJECT(row->row),"kernel_row",row);

    return row;
}


void *yon_modules_list_load(main_window *widgets){
    if (!getuid()||!yon_char_is_empty(config(source_parameter))){
        int size;
        config_str modules = yon_config_load(yon_debug_output("%s\n",get_modules_command),&size);
        for(int i=1;i<size;i++){
            yon_char_remove_last_symbol(modules[i],'\n');
            int parsed_size=0;
            config_str parsed = NULL;
            parsed = yon_char_parse(modules[i],&parsed_size,";");
            if (parsed_size<5){
                continue;
            }
            struct row_data *row = malloc(sizeof(struct row_data));
            memset(row,0,sizeof(struct row_data));
            row->version = parsed[3];
            row->name = parsed[1];
            row->tags = yon_char_replace(parsed[2]," ",", ");
            row->description = parsed[5];
            row->widgets=widgets;
            row->source = parsed[0];

            char sizemod;
            char *temp = yon_char_from_double(yon_size_long_convert_automatic(atol(parsed[4]),&sizemod));
            char *size_str = yon_size_get_name_from_letter(sizemod);
            row->size_raw = (unsigned long)atol(parsed[4]);
            row->size = yon_char_unite(temp," ", size_str,NULL);
            free(temp);
            g_idle_add((GSourceFunc)yon_os_component_insert,row);
            // yon_os_component_insert(row);
        }
        if (main_config.modules_size) yon_char_parsed_free(main_config.modules,main_config.modules_size);
        main_config.modules = modules;
        main_config.modules_size = size;
    }
        g_idle_add((GSourceFunc)yon_spinner_switch_off,widgets->OSSpinner);
        g_idle_add((GSourceFunc)yon_os_components_load,widgets);
        // yon_spinner_switch_off(GTK_SPINNER(widgets->OSSpinner));
        // yon_os_components_load(widgets);
    g_thread_exit(NULL);
}

void yon_os_row_setup(os_row *row, char *name, char *version,char *tags, char *description,char *source, char *size){
    row->name = yon_char_new(name);
    row->source = yon_char_new(source);
    row->modules = yon_char_new(name);

    char *description_full = yon_char_new(description);
    if (yon_char_is_empty(source)||yon_char_check_begins_with(source,"(local)/")){
        gtk_widget_hide(gtk_widget_get_parent(row->SourceLabel));
    } else {
        gtk_label_set_text(GTK_LABEL(row->SourceLabel),source);
    }
    
    char *label_markup = yon_char_unite("<a href=\"\">",name,"</a>",NULL);
    gtk_label_set_markup(GTK_LABEL(row->NameLabel),label_markup);
    gtk_label_set_label(GTK_LABEL(row->VersionLabel),version);
    gtk_label_set_label(GTK_LABEL(row->DescriptionLabel),description_full);
    gtk_label_set_label(GTK_LABEL(row->SizeLabel),size);

    yon_kernel_row_setup_tags((kernel_row*)row,tags);
    free(size);
    free(description_full);
    free(label_markup);
}

gboolean yon_os_component_insert(struct row_data *row_input){
    os_row *row = yon_os_row_new();

    main_window *widgets = row_input->widgets;
    g_signal_connect(G_OBJECT(row->InstallCheck),"toggled",G_CALLBACK(yon_os_components_check_packages_size),widgets);
    gtk_list_box_insert(GTK_LIST_BOX(widgets->OSSoftwareListBox),row->row,-1);
    yon_os_row_setup(row,row_input->name,row_input->version,row_input->tags,!yon_char_is_empty(row_input->description)?(_(row_input->description)):"", row_input->source, row_input->size);
    row->size_raw = row_input->size_raw;
    char *modules = config(modules_parameter);
    if (yon_char_is_empty(modules)||yon_char_check_element(modules,row_input->name,",")||!strcmp(modules,"auto")){
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(row->InstallCheck),1);
    }
    return G_SOURCE_REMOVE;
}

gboolean yon_spinner_switch_off(GtkSpinner *target){
    gtk_spinner_stop(target);
    gtk_widget_hide(GTK_WIDGET(target));
    return G_SOURCE_REMOVE;
}

gboolean yon_os_components_load(main_window *widgets){
    int size=0;
    GList *list = gtk_container_get_children(GTK_CONTAINER(widgets->OSSoftwareListBox));
    if (!list){
        gtk_widget_show(widgets->OSSoftwareEmptyLabel);
        return G_SOURCE_REMOVE;
    } else {
        gtk_widget_hide(widgets->OSSoftwareEmptyLabel);
    }
    GList *iter;
    for(iter = list;iter;iter=iter->next){
        os_row *row = g_object_get_data(iter->data,"kernel_row");
        int cur_size = 0;
        gtk_widget_realize(row->RowBox);
        gtk_widget_get_preferred_width(row->RowBox,&cur_size,NULL);
        if (size<cur_size)size=cur_size;
    }
    for(iter = list;iter;iter=iter->next){
        os_row *row = g_object_get_data(iter->data,"kernel_row");
        gtk_widget_set_size_request(row->RowBox,size,-1);
    }

    char *modules = config(modules_parameter);
    if (!yon_char_is_empty(modules)){
        int parsed_size;
        config_str parsed = yon_char_parse(modules,&parsed_size,",");
        for(iter = list;iter;iter=iter->next){
            os_row *row = g_object_get_data(iter->data,"kernel_row");
            char *target = row->source;
            if (!parsed_size||!strcmp(parsed[0],"auto")||yon_char_parsed_check_exist(parsed,parsed_size,target)>-1){
                gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(row->InstallCheck),1);
            } else {
                gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(row->InstallCheck),0);
            }
        }
        yon_char_parsed_free(parsed,parsed_size);
    }
    return G_SOURCE_REMOVE;
}

void yon_modules_missed_func(main_window *widgets){
    yon_ubl_status_box_spawn(GTK_CONTAINER(widgets->StatusBox),MAIN_COMPONENTS_NOT_FOUND_LABEL,5,BACKGROUND_IMAGE_FAIL_TYPE);
}

void yon_os_components_init(main_window *widgets){
    if (!main_config.configure_mode){
        yon_config_update_by_args(main_config.config_load_path, modules_parameter,NULL);
    }
    GList *list = gtk_container_get_children(GTK_CONTAINER(widgets->OSSoftwareListBox));
        GList *iter;
    for (iter=list;iter;iter=iter->next){
        gtk_widget_destroy(GTK_WIDGET(iter->data));
    }
    if (!gtk_widget_get_parent(widgets->OSSpinner))
        gtk_overlay_add_overlay(GTK_OVERLAY(widgets->OSOverlay),widgets->OSSpinner);
    gtk_spinner_start(GTK_SPINNER(widgets->OSSpinner));
    gtk_widget_show(widgets->OSSpinner);
    g_thread_new("geag",(GThreadFunc)yon_modules_list_load,widgets);
    while(gtk_events_pending()) gtk_main_iteration();
}

// void on_software_uncheck_all(GtkWidget *, main_window *widgets){
//     int active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widgets->AdditionalComponentsUncheckAllCheck));
//     switch(active){
//         case 1:{
//             GList *list = gtk_container_get_children(GTK_CONTAINER(widgets->AdditionalComponentsList));
//             GList *iter;
//             for(iter = list;iter;iter=iter->next){
//                 os_row *row = g_object_get_data(iter->data,"kernel_row");
//                 int sensitive = gtk_widget_get_sensitive(row->InstallCheck);
//                 if (sensitive){
//                     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(row->InstallCheck),0);
//                 }
//             }
//         } break;
//     }
//     gtk_widget_hide(widgets->AdditionalComponentsUncheckAllCheck);
//     g_signal_handlers_block_by_func(G_OBJECT(widgets->AdditionalComponentsUncheckAllCheck),on_software_switch_all,widgets);
//     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widgets->AdditionalComponentsUncheckAllCheck),0);
//     g_signal_handlers_unblock_by_func(G_OBJECT(widgets->AdditionalComponentsUncheckAllCheck),on_software_switch_all,widgets);
// }

void on_software_switch_all(GtkWidget *self,main_window *widgets){
    g_signal_handlers_block_by_func(G_OBJECT(self),G_CALLBACK(on_software_switch_all),widgets);
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(self),0);
    g_signal_handlers_unblock_by_func(G_OBJECT(self),G_CALLBACK(on_software_switch_all),widgets);
    int active = !!g_object_get_data(G_OBJECT(self),"uncheck");
    GList *list = gtk_container_get_children(GTK_CONTAINER(widgets->AdditionalComponentsList));
    GList *iter;
    for(iter = list;iter;iter=iter->next){
        os_row *row = g_object_get_data(iter->data,"kernel_row");
        int sensitive = gtk_widget_get_sensitive(row->InstallCheck);
        if (sensitive){
            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(row->InstallCheck),!active);
        }
    }
    switch(active){
        case 0: gtk_button_set_label(GTK_BUTTON(self),UNCHECK_ALL_LABEL);
        g_object_set_data(G_OBJECT(self),"uncheck",widgets);
        break;
        case 1: gtk_button_set_label(GTK_BUTTON(self),CHECK_ALL_LABEL);
        g_object_set_data(G_OBJECT(self),"uncheck",NULL);
    }
}

int yon_software_save(main_window *widgets){
    GList *list = gtk_container_get_children(GTK_CONTAINER(widgets->AdditionalComponentsList));
    GList *iter;
    char *config_val = config(packages_parameter);
    if (yon_char_is_empty(config_val)){
        yon_config_register(packages_parameter,packages_parameter_command,NULL);
    }
    for(iter = list;iter;iter=iter->next){
        os_row *row = g_object_get_data(iter->data,"kernel_row");
        char *target = row->name;
        int status = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(row->InstallCheck));
        if (status){
            if (!yon_char_check_element(config_val,target,",")){
                if (gtk_widget_get_sensitive(row->InstallCheck)){
                    yon_config_append_elements(packages_parameter,target,",");
                }
            }
        } else{
            char *append_str = yon_char_replace(target," ",",");
            yon_config_remove_elements(packages_parameter,target,",");
            free(append_str);
        }
    }
    g_list_free(list);
    if (!main_config.configure_mode){
        int size;
        config_str parameters = yon_config_get_save_parameters_by_key(&size,packages_parameter,NULL);
        if (parameters){
            char *command_parameters = yon_char_parsed_to_string(parameters,size," -- ");
            char *command = yon_char_unite(ubconfig_dull_command,"--target system ",command_parameters,NULL);
            if (!system(yon_debug_output("%s\n",command))){}
            free(command);
            yon_char_parsed_free(parameters,size);
        }
    }
    return 1;
}


int yon_software_check_packages_size(GtkWidget *, main_window *widgets){
        long pacman_size = 0;
    {
        int active = 1;
        GList *list = gtk_container_get_children(GTK_CONTAINER(widgets->AdditionalComponentsList));
        GList *listiter;
        for (listiter=list;listiter;listiter=listiter->next){
            os_row *row = g_object_get_data(G_OBJECT(listiter->data),"kernel_row");
            if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(row->InstallCheck))){
                long cur_size = row->size_raw;
                pacman_size += cur_size;
                if (gtk_widget_get_sensitive(row->InstallCheck)){
                    // gtk_widget_show(widgets->AdditionalComponentsUncheckAllCheck);
                    active = 0;
                }
            }
        }
        switch(active){
            case 0: gtk_button_set_label(GTK_BUTTON(widgets->AdditionalComponentsUncheckAllCheck),UNCHECK_ALL_LABEL);
            g_object_set_data(G_OBJECT(widgets->AdditionalComponentsUncheckAllCheck),"uncheck",widgets);
            break;
            case 1: gtk_button_set_label(GTK_BUTTON(widgets->AdditionalComponentsUncheckAllCheck),CHECK_ALL_LABEL);
            g_object_set_data(G_OBJECT(widgets->AdditionalComponentsUncheckAllCheck),"uncheck",NULL);
        }
    }
    {
        GtkTreeIter iter;
        GtkTreeModel *model = GTK_TREE_MODEL(widgets->PacmanSoftwareChosenList);
        for_iter(model, &iter){
            char *name;
            gtk_tree_model_get(model,&iter,1,&name,-1);
            long size = yon_packages_get_installed_size(YON_PACKAGES_ALL,name);
            pacman_size+=size;
        }
        char *overall_str = NULL;
        if (pacman_size){
            overall_str = yon_size_long_convert_automatic_to_string(pacman_size);
        } else {
            overall_str = yon_char_unite("0 ",yon_size_get_name_from_letter('K'),NULL);
        }
        gtk_label_set_text(GTK_LABEL(widgets->AdditionalComponentsOverallSizeLabel),overall_str);
        if (!yon_char_is_empty(overall_str)) free(overall_str);
    }
    
    return 1;
}

gboolean yon_software_insert(struct row_data *row_input){
    os_row *row = yon_os_row_new();

    main_window *widgets = row_input->widgets;
    g_signal_connect(G_OBJECT(row->InstallCheck),"toggled",G_CALLBACK(yon_software_check_packages_size),widgets);
    gtk_list_box_insert(GTK_LIST_BOX(widgets->AdditionalComponentsList),row->row,-1);
    yon_os_row_setup(row,row_input->name,row_input->version,row_input->tags,_(row_input->description),NULL,row_input->size);
    row->size_raw = row_input->size_raw;

    char *modules = config(packages_parameter);
    if (yon_char_check_element(modules,row_input->name,",")){
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(row->InstallCheck),1);
    } else {
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(row->InstallCheck),0);
    }
    char *modules_prm = config(modules_parameter);
    char *modules_param = NULL;
    if (modules_prm&&!strcmp(modules_prm,"auto")){
        int final_size = 0;
        config_str final = NULL;
        for (int i=0;i<main_config.modules_size;i++){
            int parsed_size=0;
            config_str parsed = yon_char_parse(main_config.modules[i],&parsed_size,";");
            yon_char_parsed_add_or_create_if_exists(final,&final_size,parsed[1]);
            yon_char_parsed_free(parsed,parsed_size);
            while(gtk_events_pending()) gtk_main_iteration();
        }
        modules_param = yon_char_parsed_to_string(final,final_size,",");
    }  else if (!yon_char_is_empty(modules_prm)){
        int final_size = 0;
        config_str final = NULL;
        for (int i=0;i<main_config.modules_size;i++){
            int parsed_size=0;
            config_str parsed = yon_char_parse(main_config.modules[i],&parsed_size,";");
            if (yon_char_check_element(modules_prm,parsed[0],",")){
                yon_char_parsed_add_or_create_if_exists(final,&final_size,parsed[1]);
            }
            yon_char_parsed_free(parsed,parsed_size);
            while(gtk_events_pending()) gtk_main_iteration();
        }
        modules_param = yon_char_parsed_to_string(final,final_size,",");
    }
    if (yon_char_check_elements(modules_param,row_input->name,",")){
        gtk_widget_set_sensitive(row->InstallCheck,0);
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(row->InstallCheck),1);
    }
    if (!yon_char_is_empty(modules_param)) free(modules_param);
    return G_SOURCE_REMOVE;
}

void yon_software_init(main_window *widgets){
    if (!main_config.configure_mode){
        yon_config_update_by_args(main_config.config_load_path, packages_parameter,NULL);
    }
    GList *list = gtk_container_get_children(GTK_CONTAINER(widgets->AdditionalComponentsList));
        GList *iter;
    for (iter=list;iter;iter=iter->next){
        os_row *row = g_object_get_data(iter->data,"kernel_row");
        free(row);
        gtk_widget_destroy(GTK_WIDGET(iter->data));
        while(gtk_events_pending()) gtk_main_iteration();
    }
    int base_size;
        config_str base = yon_packages_find(YON_PACKAGES_ALL,"ubm-",(gsize*)&base_size);
    for (int i=0;i<base_size;i++){
        struct row_data *row = malloc(sizeof(struct row_data));
        row->version = yon_packages_get_version(YON_PACKAGES_ALL,base[i]);
        row->name = yon_char_new(base[i]);
        row->tags = yon_packages_get_groups(YON_PACKAGES_ALL,base[i]);
        int parsed_size;
        config_str tags_parsed = yon_char_parse(row->tags,&parsed_size,", ");
        if (parsed_size){
            int ubmodule_pos = yon_char_parsed_check_exist(tags_parsed,parsed_size,"ubmodule");
            if (ubmodule_pos>-1){
                free(tags_parsed[ubmodule_pos]);
                tags_parsed[ubmodule_pos] = NULL;
                row->tags = yon_char_parsed_to_string(tags_parsed,parsed_size,", ");

            }
            yon_char_parsed_free(tags_parsed,parsed_size);
        }
        row->description = yon_packages_get_description(YON_PACKAGES_ALL,base[i]);
        long size = yon_packages_get_installed_size(YON_PACKAGES_ALL,base[i]);
            char mod = '\0';
            double size_converted = yon_size_long_convert_automatic(size,&mod);
            
            char *size_str = yon_char_unite(yon_char_from_double(size_converted)," ", yon_size_get_name_from_letter(mod),NULL);
        row->size_raw = size;
        row->size = size_str;
        row->widgets=widgets;
        yon_software_insert(row);
        // g_idle_add((GSourceFunc)yon_software_insert,row);
    while(gtk_events_pending()) gtk_main_iteration();
    }
    yon_spinner_switch_off(GTK_SPINNER(widgets->OSSpinner));
    // g_idle_add((GSourceFunc)yon_spinner_switch_off,widgets->OSSpinner);
        yon_char_parsed_free(base,base_size);
    yon_software_check_packages_size(NULL,widgets);
    return ;
}

int yon_pacman_software_save(main_window *widgets){
    if (!yon_installation_check_packages_size(widgets)) return 0;
    GtkTreeIter iter;
    GtkTreeModel *model = GTK_TREE_MODEL(widgets->PacmanSoftwareChosenList);
    char *old_packages = config(packages_parameter);
    yon_config_register(packages_parameter,packages_parameter_command,NULL);
    int status = yon_char_is_empty(old_packages);
    yon_config_set_status(packages_parameter,status-1);

    for_iter(model,&iter){
        char *target;
        int sensitive=0;
        gtk_tree_model_get(model,&iter,1,&target,6,&sensitive,-1);
        if (sensitive){
            yon_config_append_element(packages_parameter,target,",");
        }
    }
    if (!main_config.configure_mode){
        int size;
        config_str parameters = yon_config_get_save_parameters_by_key(&size,packages_parameter,NULL);
        if (parameters){
            char *command_parameters = yon_char_parsed_to_string(parameters,size," -- ");
            char *command = yon_char_unite(ubconfig_dull_command,"--target system ",command_parameters,NULL);
            if (!system(yon_debug_output("%s\n",command))){}
            free(command);
            yon_char_parsed_free(parameters,size);
        }
    }
    return 1;
}

void yon_pacman_init(main_window *widgets){
    if (!main_config.configure_mode){
        yon_config_update_by_args(main_config.config_load_path, packages_parameter,NULL);
    }
    gtk_list_store_clear(widgets->PacmanSoftwareChosenList);
    char *pacman_packages = config(packages_parameter);
    char *modules_packages = config(modules_parameter);

    int size=0;
    config_str parsed = yon_char_parse(pacman_packages,&size,",");
    for (int i=0;i<size;i++){
        char *description = yon_packages_get_description(YON_PACKAGES_ALL,parsed[i]);
        char *version = yon_packages_get_version(YON_PACKAGES_ALL,parsed[i]);
        long pkgsize = yon_packages_get_installed_size(YON_PACKAGES_ALL,parsed[i]);
        char mod = '\n';
        double size_converted = yon_size_long_convert_automatic(pkgsize,&mod);
        char *size_str = yon_char_unite(yon_char_from_double(size_converted)," ", yon_size_get_name_from_letter(mod),NULL);
        GtkTreeIter iter;
        gtk_list_store_append(widgets->PacmanSoftwareChosenList,&iter);
        gtk_list_store_set(widgets->PacmanSoftwareChosenList,&iter,0,1,1,parsed[i],2,version,3,_(description),4,size_str,6,1,-1);
        free(size_str);
    while(gtk_events_pending()) gtk_main_iteration();
    }
    yon_char_parsed_free(parsed,size);

    size=0;
    if (modules_packages&&!strcmp(modules_packages,"auto")){
        int final_size;
        config_str final = NULL;
        for (int i=0;i<main_config.modules_size;i++){
            int parsed_size=0;
            config_str parsed = yon_char_parse(main_config.modules[i],&parsed_size,";");
            yon_char_parsed_add_or_create_if_exists(final,&final_size,parsed[1]);
            yon_char_parsed_free(parsed,parsed_size);
        }
        modules_packages = yon_char_parsed_to_string(final,final_size,",");
    }  else if (!yon_char_is_empty(modules_packages)){
        int final_size = 0;
        config_str final = NULL;
        for (int i=0;i<main_config.modules_size;i++){
            int parsed_size=0;
            config_str parsed = yon_char_parse(main_config.modules[i],&parsed_size,";");
            if (yon_char_check_element(modules_packages,parsed[0],",")){
                yon_char_parsed_add_or_create_if_exists(final,&final_size,parsed[1]);
            }
            yon_char_parsed_free(parsed,parsed_size);
        }
        modules_packages = yon_char_parsed_to_string(final,final_size,",");
    }
    while(gtk_events_pending()) gtk_main_iteration();
    parsed = yon_char_parse(modules_packages,&size,",");
    for (int i=1;i<size;i++){

        char *description = yon_packages_get_description(YON_PACKAGES_ALL,parsed[i]);
        char *version = yon_packages_get_version(YON_PACKAGES_ALL,parsed[i]);
        long pkgsize = yon_packages_get_installed_size(YON_PACKAGES_ALL,parsed[i]);
        char mod = '\n';
        double size_converted = yon_size_long_convert_automatic(pkgsize,&mod);
        char *size_str = yon_char_unite(yon_char_from_double(size_converted)," ", yon_size_get_name_from_letter(mod),NULL);
        GtkTreeIter iter;
        gtk_list_store_append(widgets->PacmanSoftwareChosenList,&iter);
        gtk_list_store_set(widgets->PacmanSoftwareChosenList,&iter,0,1,1,parsed[i],2,version,3,_(description),4,size_str,6,0,-1);
        free(size_str);
        while(gtk_events_pending()) gtk_main_iteration();
    }
    yon_pacman_software_update_overall_size(widgets);
    yon_char_parsed_free(parsed,size);
}

void on_pacman_software_all_toggled(GtkWidget *, char *path, main_window *widgets){
    GtkTreeIter iter;
    char *name, *type, *description, *size_str;
    gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(widgets->PacmanSoftwareAllList),&iter,path);
    gtk_tree_model_get(GTK_TREE_MODEL(widgets->PacmanSoftwareAllList),&iter,1,&name,2,&type,3,&description,4,&size_str,-1);
    gtk_list_store_remove(widgets->PacmanSoftwareAllList,&iter);
    gtk_list_store_append(widgets->PacmanSoftwareChosenList,&iter);
    gtk_list_store_set(widgets->PacmanSoftwareChosenList,&iter,0,1,1,name,2,type,3,description,4,size_str,6,1,-1);
    g_hash_table_add(widgets->pacmanchosen,yon_char_new(name));
    yon_pacman_software_update_overall_size(widgets);

}

void yon_pacman_software_update_overall_size(main_window *widgets){
        long pacman_size = 0;
    {
        GtkTreeIter iter;
        GtkTreeModel *model = GTK_TREE_MODEL(widgets->PacmanSoftwareChosenList);
        for_iter(model, &iter){
            char *name;
            int sensitive=0;
            gtk_tree_model_get(model,&iter,1,&name,6,&sensitive,-1);
            if (sensitive){
                long size = yon_packages_get_installed_size(YON_PACKAGES_ALL,name);
                pacman_size+=size;
            }
        }
        char *overall_str = NULL;
        if (pacman_size){
            overall_str = yon_size_long_convert_automatic_to_string(pacman_size);
        } else {
            overall_str = yon_char_unite("0 ",yon_size_get_name_from_letter('K'),NULL);
        }
        gtk_label_set_text(GTK_LABEL(widgets->PacmanChosenLabel),overall_str);
        if (!yon_char_is_empty(overall_str)) free(overall_str);
    }
    {
        GList *list = gtk_container_get_children(GTK_CONTAINER(widgets->OSSoftwareListBox));
        GList *listiter;
        for (listiter=list;listiter;listiter=listiter->next){
            os_row *row = g_object_get_data(G_OBJECT(listiter->data),"kernel_row");
            if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(row->InstallCheck))){
                long cur_size = row->size_raw;
                pacman_size += cur_size;
            }
        }
        char *final_modules_size = NULL;
        if (pacman_size){
            final_modules_size = yon_size_long_convert_automatic_to_string(pacman_size);
        } else {
            final_modules_size = yon_char_unite("0 ",yon_size_get_name_from_letter('K'),NULL);
        }
        gtk_label_set_text(GTK_LABEL(widgets->PacmanOverallSizeLabel),final_modules_size);
        if (!yon_char_is_empty(final_modules_size)) free(final_modules_size);
    }
}

void on_pacman_software_chosen_toggled(GtkWidget *, char *path, main_window *widgets){
    GtkTreeIter iter;
    char *name, *type, *description, *size_str;
    int sensitive=0;
    gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(widgets->PacmanSoftwareChosenList),&iter,path);
    gtk_tree_model_get(GTK_TREE_MODEL(widgets->PacmanSoftwareChosenList),&iter,1,&name,2,&type,3,&description,4,&size_str,6,&sensitive,-1);
    if (sensitive){
        gtk_list_store_remove(widgets->PacmanSoftwareChosenList,&iter);
        gtk_list_store_append(widgets->PacmanSoftwareAllList,&iter);
        gtk_list_store_set(widgets->PacmanSoftwareAllList,&iter,0,0,1,name,2,type,3,description,4,size_str,-1);
        g_hash_table_remove(widgets->pacmanchosen,name);
        yon_pacman_software_update_overall_size(widgets);
    }
}

gboolean yon_pacman_fill(struct pacman_struct *pacman){
    main_window *widgets = pacman->widgets;
    config_str loaded = pacman->packages;
    int size = pacman->packages_size;


    for (int i=0;i<size;i++){
        if (yon_char_is_empty(loaded[i])||g_hash_table_contains(widgets->pacmanchosen,loaded[i])) continue;
        char *version = yon_packages_get_version(YON_PACKAGES_SYNC,loaded[i]);
        char *description = yon_packages_get_description(YON_PACKAGES_SYNC,loaded[i]);
        GtkTreeIter iter;
        long pkgsize = yon_packages_get_installed_size(YON_PACKAGES_SYNC,loaded[i]);
        char mod = '\n';
        double size_converted = yon_size_long_convert_automatic(pkgsize,&mod);
        char *size_str = yon_char_unite(yon_char_from_double(size_converted)," ", yon_size_get_name_from_letter(mod),NULL);
        gtk_list_store_append(widgets->PacmanSoftwareAllList,&iter);
        gtk_list_store_set(widgets->PacmanSoftwareAllList,&iter,0,0,1,loaded[i],2,version,3,_(description),4,size_str,-1);
    }
    yon_pacman_software_update_overall_size(widgets);
    yon_char_parsed_free(loaded,size);
    gtk_widget_set_sensitive(widgets->PacmanSoftwareSearchEntry,1);
    gtk_widget_set_sensitive(widgets->PacmanSoftwareChosenPackagesTree,1);
    g_object_ref(G_OBJECT(widgets->MainSpinner));
    gtk_container_remove(GTK_CONTAINER(widgets->PacmanLoadingOverlay),widgets->MainSpinner);
    return G_SOURCE_REMOVE;
}

void *yon_pacman_load(struct pacman_struct *pacman){
    const char *find_package = pacman->find_package;
        // char *command = get_local_module_info_command(find_package);
        pacman->packages = yon_packages_find(YON_PACKAGES_SYNC,find_package,&pacman->packages_size);
            g_idle_add((GSourceFunc)yon_pacman_fill,pacman);
            // yon_pacman_fill(pacman);
        return NULL;
}

void on_pacman_search_enter(GtkEntry *self, main_window *widgets){
    on_pacman_icon_press(self,GTK_ENTRY_ICON_SECONDARY,NULL,widgets);
    while (gtk_events_pending()) gtk_main_iteration();
    gtk_widget_grab_focus(widgets->PacmanSoftwareSearchEntry);
}

void on_pacman_icon_press(GtkEntry *self,GtkEntryIconPosition icon_pos,GdkEvent* ,main_window *widgets){
    if(icon_pos != GTK_ENTRY_ICON_SECONDARY) return;
    
    gtk_list_store_clear(widgets->PacmanSoftwareAllList);

    const char *find_package = gtk_entry_get_text(self);
    if (strlen(find_package)<2) return;
    struct pacman_struct *pacman = new (struct pacman_struct);
    pacman->widgets=widgets;
    pacman->find_package=find_package;
    gtk_widget_set_sensitive(widgets->PacmanSoftwareSearchEntry,0);
    gtk_widget_set_sensitive(widgets->PacmanSoftwareChosenPackagesTree,0);
    gtk_overlay_add_overlay(GTK_OVERLAY(widgets->PacmanLoadingOverlay),widgets->MainSpinner);
    g_thread_new("pacman_modules_get_thread",(GThreadFunc)yon_pacman_load,pacman);
}