#include "upac-gtk.h"

gboolean switch_all = 0;

void yon_groups_switch_all_recursive(main_window *widgets, GtkTreeIter *parent){
    if (!parent) return;
    GtkTreeIter iter;
    gtk_tree_model_iter_children(GTK_TREE_MODEL(widgets->PackagesList),&iter,parent);
    int active = !g_object_get_data(G_OBJECT(widgets->UncheckAllCheck),"uncheck");
    for (int valid = 1; valid; valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(widgets->PackagesList),&iter)){
        gtk_tree_store_set(widgets->PackagesList,&iter,0,active,-1);
        if (gtk_tree_model_iter_has_child(GTK_TREE_MODEL(widgets->PackagesList),&iter)){
            yon_groups_switch_all_recursive(widgets,&iter);
        }
        
    }
}

void yon_groups_switch_all(main_window *widgets){
    int active = !g_object_get_data(G_OBJECT(widgets->UncheckAllCheck),"uncheck");
    GtkTreeIter iter;
    switch_all=1;
    for_iter(widgets->PackagesList,&iter){
        gtk_tree_store_set(widgets->PackagesList,&iter,0,active,-1);
        if (gtk_tree_model_iter_has_child(GTK_TREE_MODEL(widgets->PackagesList),&iter)){
            yon_groups_switch_all_recursive(widgets,&iter);
        }
    }
    switch_all=0;
    yon_size_update(widgets);

}

GtkTreeIter *yon_groups_category_check(GtkTreeStore *target,char *category){
    GtkTreeIter iter;
    GtkTreeIter *ret_iter = NULL;
    for_iter(target,&iter){
        char *cur_category;
        gtk_tree_model_get(GTK_TREE_MODEL(target),&iter,1,&cur_category,-1);
        if (!strcmp(cur_category,category)){
            ret_iter = gtk_tree_iter_copy(&iter);
        }
    }
    return ret_iter;
}
GtkTreeIter *yon_groups_subcategory_check(GtkTreeStore *target, GtkTreeIter *parent_iter, char *category){
    GtkTreeIter iter;
    GtkTreeIter *ret_iter = NULL;
    int valid = gtk_tree_model_iter_children(GTK_TREE_MODEL(target),&iter,parent_iter);
    for(; valid; valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(target),&iter)){
        char *cur_category;
        gtk_tree_model_get(GTK_TREE_MODEL(target),&iter,1,&cur_category,-1);
        if ((yon_char_is_empty(cur_category)&&yon_char_is_empty(category))||!strcmp(cur_category,category)){
            ret_iter = gtk_tree_iter_copy(&iter);
        }
    }
    return ret_iter;
}

void yon_groups_remove_empty_groups(main_window *widgets){
    GtkTreeModel *model = GTK_TREE_MODEL(widgets->PackagesList);
    GtkTreeIter iter;
    for_iter(model,&iter){
        if (gtk_tree_model_iter_has_child(model,&iter)){
            GtkTreeIter subiter;
            for (int valid2 = gtk_tree_model_iter_children(model,&subiter,&iter);valid2;valid2 = gtk_tree_model_iter_next(model,&subiter)){
                char *packages;
                gtk_tree_model_get(model,&subiter,5,&packages,-1);
                if (yon_char_is_empty(packages)&&!gtk_tree_model_iter_has_child(model,&subiter)){
                    gtk_tree_store_remove(widgets->PackagesList,&subiter);
                    if (!gtk_tree_model_iter_children(model,&subiter,&iter)){
                        valid2=0;
                        break;
                    }
                }
            }
        } else {
            gtk_tree_store_remove(widgets->PackagesList,&iter);
            if (!gtk_tree_model_get_iter_first(model,&iter)){
                valid=0;
                break;
            }
        }
    }
}

void yon_on_groups_chosen(GtkWidget *, char *path, main_window *widgets){
    GtkTreeIter iter;
    gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(widgets->PackagesList),&iter,path);
    int status = 0;
    gtk_tree_model_get(GTK_TREE_MODEL(widgets->PackagesList),&iter,0,&status,-1);
    gtk_tree_store_set(widgets->PackagesList,&iter,0,!status,-1);

    if (!switch_all){
        yon_size_update(widgets);
    }
}

void yon_groups_tab_init(main_window *widgets){
    while(gtk_events_pending()) gtk_main_iteration();
    gtk_tree_store_clear(widgets->PackagesList);

    int size =0;
    config_str packages = yon_resource_open_file(groups_list_path,&size);
    for (int i=1;i<size;i++){
        int parsed_size;
        config_str parsed = yon_char_parse(packages[i],&parsed_size,";");
        GtkTreeIter *category_iter = yon_groups_category_check(widgets->PackagesList,parsed[0]);
        char *name_render = yon_char_replace(parsed[2],","," ");
        int final_size = 0;
        config_str final = NULL;
        int modules_parsed_size = 0;
        config_str modules_parsed = yon_char_parse(parsed[2],&modules_parsed_size," ");
        for (int j=0;j<modules_parsed_size;j++){
            yon_char_parsed_add_or_create_if_exists(final,&final_size,modules_parsed[j]);
        }
        while(gtk_events_pending()) gtk_main_iteration();
        yon_char_parsed_free(modules_parsed,modules_parsed_size);
        char *modules_string = yon_char_parsed_to_string(final,final_size,"\t");
        int installed = yon_packages_check_installed(parsed[2]);
        if (category_iter){
            if (!yon_char_is_empty(parsed[1])){
                GtkTreeIter *subcategory_iter = yon_groups_subcategory_check(widgets->PackagesList,category_iter,parsed[1]);
                if (subcategory_iter){
                    GtkTreeIter package_iter;
                    gtk_tree_store_append(widgets->PackagesList,&package_iter,subcategory_iter);
                    char *full_string = yon_char_unite("<b>",name_render,"</b>\n",_(parsed[3]),NULL);
                    gtk_tree_store_set(widgets->PackagesList,&package_iter,
                    0,installed,1,modules_string,
                    2,full_string,3,1,
                    4,installed,5,modules_string,
                    6,yon_packages_get_installed_size(YON_PACKAGES_ALL,parsed[2]),-1);
                    free(full_string);
                    gtk_tree_iter_free(subcategory_iter);
                } else {
                    GtkTreeIter subcatiter;
                    GtkTreeIter package_iter;
                    gtk_tree_store_append(widgets->PackagesList,&subcatiter,category_iter);
                    gtk_tree_store_set(widgets->PackagesList,&subcatiter,1,parsed[1],2,_(parsed[1]),3,0,-1);
                    gtk_tree_store_append(widgets->PackagesList,&package_iter,&subcatiter);
                    char *full_string = yon_char_unite("<b>",name_render,"</b>\n",_(parsed[3]),NULL);
                    gtk_tree_store_set(widgets->PackagesList,&package_iter,0,installed,1,modules_string,
                    2,full_string,3,1,
                    4,installed,5,modules_string,
                    6,yon_packages_get_installed_size(YON_PACKAGES_ALL,parsed[2]),-1);
                    free(full_string);
                }
            } else {
                    GtkTreeIter package_iter;
                    gtk_tree_store_append(widgets->PackagesList,&package_iter,category_iter);
                    char *full_string = yon_char_unite("<b>",name_render,"</b>\n",_(parsed[3]),NULL);
                    gtk_tree_store_set(widgets->PackagesList,&package_iter,0,installed,1,modules_string,
                    2,full_string,3,1,
                    4,installed,5,modules_string,
                    6,yon_packages_get_installed_size(YON_PACKAGES_ALL,parsed[2]),-1);
                    free(full_string);
            }
            gtk_tree_iter_free(category_iter);
        } else {
            if (!yon_char_is_empty(parsed[1])){
                GtkTreeIter subcategory_iter;
                GtkTreeIter catiter;
                GtkTreeIter package_iter;
                gtk_tree_store_append(widgets->PackagesList,&catiter,NULL);
                gtk_tree_store_set(widgets->PackagesList,&catiter,1,parsed[0],2,_(parsed[0]),3,0,-1);
                gtk_tree_store_append(widgets->PackagesList,&subcategory_iter,&catiter);
                gtk_tree_store_set(widgets->PackagesList,&subcategory_iter,1,parsed[1],2,_(parsed[1]),3,0,-1);
                gtk_tree_store_append(widgets->PackagesList,&package_iter,&subcategory_iter);
                char *full_string = yon_char_unite("<b>",name_render,"</b>\n",_(parsed[3]),NULL);
                gtk_tree_store_set(widgets->PackagesList,&package_iter,0,installed,1,modules_string,
                2,full_string,3,1,
                4,installed,5,modules_string,
                6,yon_packages_get_installed_size(YON_PACKAGES_ALL,parsed[2]),-1);
                free(full_string);
            } else {
                GtkTreeIter package_iter;
                GtkTreeIter catiter;
                gtk_tree_store_append(widgets->PackagesList,&catiter,NULL);
                gtk_tree_store_set(widgets->PackagesList,&catiter,1,parsed[0],2,_(parsed[0]),3,0,-1);
                gtk_tree_store_append(widgets->PackagesList,&package_iter,&catiter);
                char *full_string = yon_char_unite("<b>",name_render,"</b>\n",_(parsed[3]),NULL);
                gtk_tree_store_set(widgets->PackagesList,&package_iter,0,installed,1,modules_string,
                2,full_string,3,1,
                4,installed,5,modules_string,
                6,yon_packages_get_installed_size(YON_PACKAGES_ALL,parsed[2]),-1);
                free(full_string);
            }
        }
        while(gtk_events_pending()) gtk_main_iteration();
    }
    yon_groups_remove_empty_groups(widgets);
    // if (!yon_char_is_empty(modules)) free(modules);
    gtk_tree_view_expand_all(GTK_TREE_VIEW(widgets->PackagesTree));
}

config_str yon_groups_get_install_packages(int *size, main_window *widgets){
    (*size)=0;
    config_str groups_packages = NULL;
    GtkTreeIter iter;
    GtkTreeModel *model = GTK_TREE_MODEL(widgets->PackagesList);
    gtk_tree_model_get_iter_first(model, &iter);
    for_iter(model,&iter){
        if (gtk_tree_model_iter_has_child(model,&iter)){
            GtkTreeIter subiter;
            gtk_tree_model_iter_children(model,&subiter,&iter);
            if (gtk_tree_model_iter_has_child(model, &subiter)){
                GtkTreeIter chiter;
                gtk_tree_model_iter_children(model, &chiter, &subiter);
                for (int valid2=1;valid2;valid2=gtk_tree_model_iter_next(model,&chiter)){
                    char *package;
                    int status;
                    int init_status;
                    gtk_tree_model_get(model,&chiter,0,&status,1,&package,4,&init_status,-1);
                    if (status&&!init_status){
                        yon_char_parsed_add_or_create_if_exists(groups_packages,size,package);
                    }
                }
            } else {
                for (int valid2=1;valid2;valid2=gtk_tree_model_iter_next(model,&subiter)){
                    char *package;
                    int status;
                    int init_status;
                    gtk_tree_model_get(model,&subiter,0,&status,1,&package,4,&init_status,-1);
                    if (status&&!init_status){
                        yon_char_parsed_add_or_create_if_exists(groups_packages,size,package);
                    }
                }
            }
        }
    }
    return groups_packages;
}

config_str yon_groups_get_remove_packages(int *size, main_window *widgets){
    (*size)=0;
    config_str groups_packages = NULL;
    GtkTreeIter iter;
    GtkTreeModel *model = GTK_TREE_MODEL(widgets->PackagesList);
    gtk_tree_model_get_iter_first(model, &iter);
    for_iter(model,&iter){
        if (gtk_tree_model_iter_has_child(model,&iter)){
            GtkTreeIter subiter;
            gtk_tree_model_iter_children(model,&subiter,&iter);
            if (gtk_tree_model_iter_has_child(model, &subiter)){
                GtkTreeIter chiter;
                gtk_tree_model_iter_children(model, &chiter, &subiter);
                for (int valid2=1;valid2;valid2=gtk_tree_model_iter_next(model,&chiter)){
                    char *package;
                    int status;
                    int init_status;
                    gtk_tree_model_get(model,&chiter,0,&status,1,&package,4,&init_status,-1);
                    if (!status&&init_status){
                        yon_char_parsed_add_or_create_if_exists(groups_packages,size,package);
                    }
                }
            } else {
                for (int valid2=1;valid2;valid2=gtk_tree_model_iter_next(model,&subiter)){
                    char *package;
                    int status;
                    int init_status;
                    gtk_tree_model_get(model,&subiter,0,&status,1,&package,4,&init_status,-1);
                    if (!status&&init_status){
                        yon_char_parsed_add_or_create_if_exists(groups_packages,size,package);
                    }
                }
            }
        }
    }
    return groups_packages;
}

long yon_groups_get_size_recursive(GtkTreeModel *model, GtkTreeIter *iter, main_window *widgets);
long yon_groups_get_size_recursive(GtkTreeModel *model, GtkTreeIter *iter, main_window *widgets){
    long overall_size = 0;
    for (int valid = 1;valid; valid = gtk_tree_model_iter_next(model,iter)){
        if (gtk_tree_model_iter_has_child(model,iter)){
            GtkTreeIter chiter;
            gtk_tree_model_iter_children(model,&chiter,iter);
            overall_size += yon_groups_get_size_recursive(model,&chiter,widgets);
        } else {
            long size;
            int status;
            int init_status;
            gtk_tree_model_get(model,iter,0,&status,4,&init_status,6,&size,-1);
            if (status&&!init_status)
                overall_size += size;
            else if (!status&&init_status)
                overall_size -= size;
        }
    }
    return overall_size;
}

long yon_groups_get_size(main_window *widgets){
    GtkTreeIter iter;
    GtkTreeModel *model = GTK_TREE_MODEL(widgets->PackagesList);
    long overall_size = 0;
    for_iter (model,&iter){
        if (gtk_tree_model_iter_has_child(model,&iter)){
            GtkTreeIter chiter;
            gtk_tree_model_iter_children(model,&chiter,&iter);
            overall_size += yon_groups_get_size_recursive(model,&chiter,widgets);
        } else {
            long size;
            int status;
            int init_status;
            gtk_tree_model_get(model,&iter,0,&status,4,&init_status,6,&size,-1);
            if (status&&!init_status)
                overall_size += size;
            else if (!status&&init_status)
                overall_size -= size;
        }
    }
    return overall_size;
}