#include "libublsettingsui-gtk3.h"
#include "libublsettingsui-gtk3-save.h"

/*
    ==============
    saving section
    ==============
*/
void yon_exit_window_loaded_config_init(template_saving_window *window, struct loaded_config *current_loaded);

gboolean _yon_presave_function_start(struct presave_info *data){
    presave_function(data->presave_argument,data->save_path);
    return G_SOURCE_REMOVE;
}

gboolean _yon_postsave_function_start(struct save_return *data){
    save_success_function(data->save_success_argument,data->file_return,data->file_save);
    return G_SOURCE_REMOVE;
}

gboolean _yon_postsave_failure_function_start(struct save_return *data){
    save_failure_function(data->save_success_argument,data->file_return,data->file_save);
    return G_SOURCE_REMOVE;
}

void _yon_saving_threaded(char *final_command){
    FILE *file = popen(final_command,"r");
    int file_save;
    config_str file_return = yon_config_load_file(file,&file_save);
    fclose(file);
    file_return = yon_char_parsed_prepend(file_return,&file_save,final_command);
    if (save_success_function)
    {
        struct save_return *data = malloc(sizeof(struct save_return));
        data->save_success_argument = save_success_argument;
        data->file_return = file_return;
        data->file_save = file_save;
        gdk_threads_add_idle((GSourceFunc)_yon_postsave_function_start,data);
    } 
}

struct loaded_config *yon_save_window_get_saved_parameters(template_saving_window *window){
    int saved_size = 0;
    GtkTreeIter iter;
    GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(window->ParametersTree));
    int valid = gtk_tree_model_get_iter_first(model,&iter);
    config_str saved_parameters=NULL;
    for (;valid;valid = gtk_tree_model_iter_next(model,&iter)){
        char *parameter, *value;
        int is_active;
        gtk_tree_model_get(model,&iter,0,&is_active,1,&parameter,3,&value,-1);
        if (is_active){
            char *final_string = yon_char_unite(parameter,"=",value,NULL);
            yon_char_parsed_add_or_create_if_exists(saved_parameters,&saved_size,final_string);
            free(final_string);
        }

    }
    struct loaded_config *final = yon_config_convert_parameter(saved_parameters,saved_size);
    struct loaded_config *current = NULL;
    
    for_iter(model,&iter){
        char *target, *section;
        gtk_tree_model_get(model,&iter,1,&target,7,&section,-1);
        struct loaded_config *found = (struct loaded_config*)yon_dictionary_get((dictionary**)&final,target);
        if (found){
            found->section=section;
        }
    }
    return final;
}

// struct __yon_save_section{
//     int save_size;
//     config_str save_config;
//     int remove_size;
//     config_str remove_config;
// } __yon_save_section;

config_str yon_loaded_config_convert_to_save_command(struct loaded_config *target, int *size,char *path){
    (*size)=0;

    config_str final_commands = NULL;

    {
        struct yon_temp_command_sections {
            dictionary_fields(yon_temp_command_sections);
            int status;
        };

        struct yon_temp_command_sections *sections = NULL;
        struct loaded_config *current;
        for_dictionaries(current,target){
            struct yon_temp_command_sections *cur_section=NULL, *found = NULL;
            if (sections){
                for_dictionaries(cur_section,sections){
                    if (!strcmp(current->section,cur_section->key)){
                        int status = yon_config_get_status(current->key);
                        if ((status==-1&&cur_section->status==-1)||(status>-1)&&cur_section->status>-1){
                            found = cur_section;
                        }
                    }
                }
                cur_section = found;
            }
            if (cur_section){
                char *parameters_for_current_command = NULL;
                if (yon_config_get_status(current->key)==-1){
                    parameters_for_current_command = yon_char_unite((char*)cur_section->data," ", current->key,NULL);
                } else {
                    parameters_for_current_command = yon_char_unite((char*)cur_section->data," ", current->key,"=\'",(char*)current->data,"\'",NULL);
                }
                free(current->data);
                cur_section->data = parameters_for_current_command;
            } else {
                char *parameters_for_current_command = NULL;
                if (yon_config_get_status(current->key)==-1){
                    parameters_for_current_command = current->key;
                } else {
                    parameters_for_current_command = yon_char_unite(current->key,"=\'",(char*)current->data,"\'",NULL);
                }
                dictionary *sections_dict = NULL;
                if (sections) sections_dict = yon_dictionary_get_last((dictionary*)sections);
                sections = malloc(sizeof(struct yon_temp_command_sections));
                sections->data=parameters_for_current_command;
                sections->first=sections;
                sections->key=yon_config_get_section_for_key(current->key);
                sections->next=NULL;
                sections->prev=NULL;
                sections->status=0;
                if (sections_dict){
                    sections_dict->next = (dictionary*)sections;
                    sections->prev=(struct yon_temp_command_sections*)sections_dict;
                    sections->first=(struct yon_temp_command_sections*)sections_dict->first;
                }
                // yon_dictionary_add_or_create_if_exists_with_data(sections_dict,current->section,parameters_for_current_command);

                sections->status=yon_config_get_status(current->key);
            }
            
        }
        config_str commands = NULL;
        {
            struct yon_temp_command_sections *current;
            for_dictionaries(current,sections){
                char *dull_command = NULL;
                if (current->status>=0){
                    dull_command = !commands?ubconfig_set_command_full(path,current->key,(char*)current->data):yon_char_unite("-- set ",current->key," ",(char*)current->data,NULL);
                } else {
                    dull_command = !commands?ubconfig_remove_command_full(path,current->key,(char*)current->data):yon_char_unite("-- remove ",current->key," ",(char*)current->data, NULL);
                }
                yon_char_parsed_add_or_create_if_exists(commands,size,dull_command);
                free(dull_command);
            }
            // struct yon_temp_command_sections *current;
            // for_dictionaries(current,sections){
            //     char *dull_command = NULL;
            //     if (current->status>=0){
            //         dull_command = ubconfig_set_command_full(path,current->key,(char*)current->data);
            //     } else {
            //         dull_command = ubconfig_remove_command_full(path,current->key,(char*)current->data);
            //     }
            //     yon_char_parsed_add_or_create_if_exists(commands,size,dull_command);
            //     free(dull_command);
            // }
        }
        return commands;
    }
}

void yon_save_window_set_presave_function(void *function, void *data){
    presave_function=function;
    presave_argument=data;
}

void yon_save_window_set_postsave_function(void *function, void *data){
    save_success_function=function;
    save_success_argument=data;
}

void yon_save_window_set_postsave_failure_function(void *function, void *data){
    save_failure_function=function;
    save_failure_argument=data;
}


/*
    ==============
    window section
    ==============
*/
void yon_save_window_set_status(template_saving_window *window,char *path,YON_CONFIG_TYPE type){
    textdomain(template_ui_LocaleName);
    window->type=type;
    window->custom_save_path=path;
    if (type==YON_CONFIG_BOTH){
        yon_ubl_status_box_spawn(GTK_CONTAINER(window->StatusBox),SAVING_GLOBAL_LOCAL_STATE_LABEL,0,BACKGROUND_IMAGE_INFO_TYPE);
    } else if (type==YON_CONFIG_GLOBAL){
        yon_ubl_status_box_spawn(GTK_CONTAINER(window->StatusBox),SAVING_GLOBAL_STATE_LABEL,0,BACKGROUND_IMAGE_INFO_TYPE);

    } else if (type==YON_CONFIG_LOCAL){
        yon_ubl_status_box_spawn(GTK_CONTAINER(window->StatusBox),SAVING_LOCAL_STATE_LABEL,0,BACKGROUND_IMAGE_INFO_TYPE);
    } else if (type==YON_CONFIG_CUSTOM){
        yon_ubl_status_box_spawn(GTK_CONTAINER(window->StatusBox),SAVING_CUSTOM_STATE_LABEL(path),0,BACKGROUND_IMAGE_INFO_TYPE);
    }
    textdomain(template_app_information.app_locale);
}

gboolean yon_save_window_destroy_if_empty(template_saving_window *window){
    GtkTreeIter iter;
    if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(window->list),&iter)){
        gtk_widget_destroy(window->Window);
        textdomain(template_ui_LocaleName);
        yon_ubl_status_box_render(NOTHING_TO_SAVE_LABEL,BACKGROUND_IMAGE_FAIL_TYPE);
        textdomain(template_app_information.app_locale);
        if (save_failure_function){

            struct save_return *data = malloc(sizeof(struct save_return));
            data->save_success_argument = save_failure_argument;
            data->file_return = NULL;
            data->file_save = 0;
            gdk_threads_add_idle((GSourceFunc)_yon_postsave_failure_function_start,data);
        }
        return 0;
    }
    return 1;
}

void on_save_window_parameter_switched(GtkCellRendererToggle *self, gchar *path, template_saving_window *window){
    GtkTreeIter iter,itar;
    if (path){
        if (gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(window->list),&itar,path)){
            gboolean is_active;
            gtk_tree_model_get(GTK_TREE_MODEL(window->list),&itar,0,&is_active,-1);
            gtk_list_store_set(window->list,&itar,0,!is_active,-1);
        }
    }
    int once_active=0;
    int valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(window->list),&iter);
    for (;valid;valid=gtk_tree_model_iter_next(GTK_TREE_MODEL(window->list),&iter)){
        int is_active;
        gtk_tree_model_get(GTK_TREE_MODEL(window->list),&iter,0,&is_active,-1);
        if (is_active){
            once_active=1;
            break;
        }
    }
    if (!once_active) gtk_widget_set_sensitive(window->SaveButton,0);
    else gtk_widget_set_sensitive(window->SaveButton,1);

}

template_saving_window *yon_saving_window_new(){
        GtkBuilder *builder = gtk_builder_new_from_resource(ui_glade_path_saving);
        template_saving_window *window = malloc(sizeof(template_saving_window));
        window->Window = yon_gtk_builder_get_widget(builder,"Window");
        window->HeaderImage = yon_gtk_builder_get_widget(builder,"HeaderImage");
        window->HeaderTopic = yon_gtk_builder_get_widget(builder,"HeaderTopic");
        window->StatusBox = yon_gtk_builder_get_widget(builder,"StatusBox");
        window->ParametersTree = yon_gtk_builder_get_widget(builder,"ParametersTree");
        window->SaveButton = yon_gtk_builder_get_widget(builder,"SaveButton");
        window->CancelButton = yon_gtk_builder_get_widget(builder,"CancelButton");
        window->ToggleCell = GTK_CELL_RENDERER(gtk_builder_get_object(builder,"ToggleCell"));
        window->list = GTK_LIST_STORE(gtk_builder_get_object(builder,"liststore1"));
        window->OldValueColumn = GTK_TREE_VIEW_COLUMN(gtk_builder_get_object(builder,"OldValueColumn"));
        window->OldValueCell = GTK_CELL_RENDERER(gtk_builder_get_object(builder,"OldValueCell"));
        window->NewValueColumn = GTK_TREE_VIEW_COLUMN(gtk_builder_get_object(builder,"NewValueColumn"));
        window->NewValueCell = GTK_CELL_RENDERER(gtk_builder_get_object(builder,"NewValueCell"));
        window->filteredModel = GTK_TREE_MODEL(gtk_builder_get_object(builder,"listfilter1"));
        yon_window_config_custom_window_setup(GTK_WINDOW(window->Window),"SaveWindow");
        char *icon_name = yon_char_append("com.ublinux.",template_app_information.app_tech_name);
        gtk_window_set_icon_name(GTK_WINDOW(window->Window),icon_name);
        gtk_window_set_title(GTK_WINDOW(window->Window),template_app_information.app_title);
        gtk_label_set_text(GTK_LABEL(window->HeaderTopic),template_app_information.app_title);
        gtk_image_set_from_pixbuf(GTK_IMAGE(window->HeaderImage),gtk_icon_theme_load_icon_for_scale(gtk_icon_theme_get_default(),yon_char_append("com.ublinux.",template_app_information.app_tech_name),32,1,GTK_ICON_LOOKUP_FORCE_SIZE,NULL));
        g_signal_connect(G_OBJECT(window->CancelButton),"clicked",G_CALLBACK(on_subwindow_close),NULL);
        g_signal_connect(G_OBJECT(window->SaveButton),"clicked", G_CALLBACK(on_save_parameters),window);
        g_signal_connect(G_OBJECT(window->ToggleCell),"toggled", G_CALLBACK(on_save_window_parameter_switched),window);
        return window;
}

/*
    ======================
    config getting section
    ======================
*/
char *yon_get_compare_config_command(va_list args,char *path,YON_CONFIG_TYPE type){
    char *cur_command;
        char *compare_command="";
        while ((cur_command=va_arg(args,char*))){
            char *temp=cur_command;
            cur_command = yon_config_parameter_prepare_command(cur_command,type!=YON_CONFIG_CUSTOM?yon_config_get_type_path(type):path,NULL,NULL);
            char *temp_command = yon_char_unite(compare_command,!yon_char_is_empty(compare_command)?";":"",cur_command,NULL);
            if (!yon_char_is_empty(compare_command)) free(compare_command);
            compare_command = temp_command;
        }
        return yon_char_is_empty(compare_command)?NULL:compare_command;
}

void yon_exit_window_loaded_config_init(template_saving_window *window, struct loaded_config *current_loaded){
        GtkTreeIter iter;
        struct loaded_config *current = NULL;
        for_dictionaries(current,current_loaded){
         
        char *compare_string = yon_char_unite("\n",(char*)current->data,NULL);
        gtk_list_store_append(window->list,&iter);
        gtk_list_store_set(window->list,&iter,1,current->key,3,(char*)current->data,4,compare_string,6,1,-1);   

        }
}

void yon_save_window_loaded_config_init(template_saving_window *window, struct loaded_config *current_loaded, struct loaded_config *config_compare){
    if (current_loaded){
        struct loaded_config *current = NULL;
        for_dictionaries(current,current_loaded){
            if (!yon_config_check_ignore(current->key)){
                dictionary *dict = NULL;
                if (!yon_config_compare_ignore_get(current->key)){
                    dict = yon_dictionary_get((dictionary**)&config_compare,current->key); // get old parameter value
                }
                gboolean status=0;
                status = yon_config_get_status(current->key);
                if (dict&&!yon_char_is_empty((char*)dict->data)&&status!=-2){
                    if (strcmp((char*)dict->data,(char*)current->data)){
                        GtkTreeIter iter;
                        if (status==0||status==-2) status = 0;
                        else status=1;
                        char *old_val = yon_char_new(current->data);
                        char *new_val = yon_char_new(dict->data);
                        if (strstr(old_val,"&")) {old_val = yon_char_replace(old_val,"&","\003");old_val = yon_char_replace(old_val,"\003","&amp;");}
                        if (strstr(old_val,">")) old_val = yon_char_replace(old_val,">","&gt;");
                        if (strstr(old_val,"<")) old_val = yon_char_replace(old_val,"<","&lt;");
                        if (strstr(new_val,"&")) {int sz = 0; config_str new_val_parsed = yon_char_parse(new_val,&sz,"&");new_val = yon_char_parsed_to_string(new_val_parsed,sz,"&amp;"); yon_char_parsed_free(new_val_parsed,sz);}
                        if (strstr(new_val,">")) new_val = yon_char_replace(new_val,">","&gt;");
                        if (strstr(new_val,"<")) new_val = yon_char_replace(new_val,"<","&lt;");
                        char *compare_string = yon_char_unite("<s>",(char*)new_val,"</s>\n",(char*)old_val,NULL);
                        gtk_list_store_append(window->list,&iter);
                        gtk_list_store_set(window->list,&iter,0,status,1,current->key,2,(char*)dict->data,3,(char*)current->data,4,compare_string,6,1,7,yon_config_get_section_for_key(current->key),-1);
                        free(compare_string);
                    }
                } else if ((strcmp((char*)current->data,""))&&status!=-2){
                    GtkTreeIter iter;
                    if (status==0||status==-2) status = 0;
                    else status=1;
                        char *old_val = yon_char_new(current->data);
                        if (strstr(old_val,"&")) {int sz = 0; config_str old_val_parsed = yon_char_parse(old_val,&sz,"&");old_val = yon_char_parsed_to_string(old_val_parsed,sz,"&amp;"); yon_char_parsed_free(old_val_parsed,sz);}
                        if (strstr(old_val,">")) old_val = yon_char_replace(old_val,">","&lt;");
                        if (strstr(old_val,"<")) old_val = yon_char_replace(old_val,"<","&gt;");
                    char *compare_string = yon_char_unite("\n",(char*)old_val,NULL);
                    gtk_list_store_append(window->list,&iter);
                    gtk_list_store_set(window->list,&iter,0,status,1,current->key,3,(char*)current->data,4,compare_string,6,1,7,yon_config_get_section_for_key(current->key),-1);
                    free(compare_string);
                }
            }
        }
    }
}

void yon_save_window_compared_config_init_unfound(template_saving_window *window, struct loaded_config *current_loaded, struct loaded_config *config_compare){
    if (config_compare){
        struct loaded_config *current = NULL;
        for_dictionaries(current,config_compare){
            if (!yon_config_check_ignore(current->key)){
                GtkTreeIter iter;
                dictionary *dict = yon_dictionary_get((dictionary**)&current_loaded,current->key);
                if (!dict){
                    GdkRGBA rgba;
                    rgba.alpha=0.8;
                    rgba.red=1;
                    rgba.blue=0.3;
                    rgba.green=0.65;
                    char *rgba_string = gdk_rgba_to_string(&rgba);
                    int status=0;
                    char *compare_string = yon_char_unite((char*)current->data,"\n",NULL);
                    gtk_list_store_append(window->list,&iter);
                    gtk_list_store_set(window->list,&iter,0,0,1,current->key,2,(char*)current->data,4,compare_string,5,rgba_string,6,1,7,current->section,-1);
                    free(compare_string);
                }
            }
        }
    }
}

int yon_config_parameter_prepare_elements(config_str target, int *size){
    int success = 0;
    for (int i=0;i<(*size);i++){
        char *start_bracket_replaced_string = yon_char_replace(target[i],"[","[\'");
        char *end_bracket_replaced_string = yon_char_replace(start_bracket_replaced_string,"]","\']");
        target[i] = end_bracket_replaced_string;
    }
    return success;
}

struct loaded_config *yon_config_convert_parameter(config_str parsed, int size){
    struct loaded_config *loaded=NULL;
    for (int i=0;i<size;i++){
        char *value = yon_char_new(parsed[i]);
        char *key = yon_char_divide_search(value,"=",-1);
        char *section = NULL;
        if (key[0]=='['){
            section = yon_char_divide_search(key," ",-1);
            free(yon_char_divide(section,yon_char_find_last(section,'/')));
            yon_char_remove_last_symbol(section,']');
        } else {
            section = yon_config_get_section_for_key(key);
        }
        if (!yon_char_is_empty(value)){
            yon_char_remove_brackets(value);
        }
        if (!loaded){
            loaded = (struct loaded_config*)malloc(sizeof(struct loaded_config));
            loaded->key=yon_char_new(key);
            loaded->first=loaded;
            loaded->next=NULL;
            loaded->prev=NULL;
            loaded->section=yon_char_new(section);
            loaded->data=yon_char_new(value);
        } else {
            loaded->next = (struct loaded_config*)malloc(sizeof(struct loaded_config));
            struct loaded_config *next=loaded->next;
            next->first=loaded->first;
            next->prev=loaded;
            next->key=yon_char_new(key);
            next->first=loaded->first;
            next->next=NULL;
            next->section=yon_char_new(section);
            next->data=yon_char_new(value);
            loaded=next;
        }
        if (!yon_char_is_empty(value)) free(value);
        if (!yon_char_is_empty(key)) free(key);
        if (!yon_char_is_empty(section)) free(section);
    }
    return loaded;
}

char *yon_command_get_section(char *command){
    int size=0;

    config_str parsed = yon_char_parse(command,&size," ");
    int get_pos = yon_char_parsed_check_exist(parsed,size,"get");
    if (get_pos==-1) return NULL;
    char *final = yon_char_new(parsed[get_pos+1]);
    yon_char_parsed_free(parsed,size);
    return final;
}

config_str yon_command_get_parameters(char *command,int *parameters_size){
    int size=0;
    config_str parameters = NULL;

    config_str parsed = yon_char_parse(command,&size," ");
    int get_pos = yon_char_parsed_check_exist(parsed,size,"get");
    if (get_pos==-1) return NULL;
    for (int i=get_pos+2;i<size;i++){
        yon_char_parsed_add_or_create_if_exists(parameters,parameters_size,parsed[i]);
    }
    yon_char_parsed_add_or_create_if_exists(parameters,parameters_size,NULL);
    yon_char_parsed_free(parsed,size);
    return parameters;
}

void yon_loaded_config_set_sections_from_sections_dictionary(struct loaded_config *loaded, dictionary *sections){
    struct loaded_config *current;
        for_dictionaries(current,loaded){
            dictionary *dict;
            for_dictionaries(dict,sections){
                        for(int i=0;((config_str)dict->data)[i+1]!=NULL;i++){
                            if (strstr(((config_str)dict->data)[i],"[*]")){
                                char *search = yon_char_new(((config_str)dict->data)[i]);
                                char *tmp = yon_char_divide_search(search,"[",-1);
                                free(search);
                                search = tmp;
                                if (strstr(current->key,search)){
                                    current->section = dict->key;
                                }
                            } else {
                                if (!strcmp(((config_str)dict->data)[i],current->key)){
                                    current->section = dict->key;
                                }
                            }
                        }
            }
        }
}

struct loaded_config *yon_config_get_compared(char *command){
    if (command){
        int size;
        config_str config_p = yon_config_load(command,&size);
            config_str temporary = NULL;
            int temp_size=0;
            if (config_p&&size>0){
            for (int i=0;i<size;i++){
                if (!yon_char_is_empty(config_p[i])&&strcmp(config_p[i],"(null)\n")){
                    yon_char_remove_last_symbol(config_p[i],'\n');
                    yon_char_parsed_add_or_create_if_exists(temporary,&temp_size,config_p[i]);
                }
            }
            yon_char_parsed_free(config_p,size);
        }
        if (!temporary) return NULL;
        struct loaded_config *loaded = yon_config_convert_parameter(temporary,temp_size);

        return loaded;
    }

}

char *yon_custom_config_init(GtkFileChooserAction type){
    filechooser_window *dialog = yon_config_file_chooser_window_new(type);
    gtk_widget_hide(dialog->ChooseFolderCheck);

    yon_gtk_window_setup(GTK_WINDOW(dialog->Window),NULL,OPEN_CONFIGURATION_FILE_LABEL,yon_char_unite("com.ublinux.",template_app_information.app_tech_name,NULL),"ConfigFilechooserWindow");
    gtk_label_set_text(GTK_LABEL(dialog->HeaderTopic),OPEN_CONFIGURATION_FILE_LABEL);
    if (type==GTK_FILE_CHOOSER_ACTION_SAVE){
        // yon_file_chooser_set_button_label(yon_char_get_localised_from_lib(LOAD_CONFIG_LABEL));

    }
    if (yon_file_chooser_start(dialog)!=GTK_RESPONSE_CANCEL){

        char *file = dialog->last_success_selection;
        if (!yon_char_is_empty(file)){
            if (!strstr(file,".ini")) file = yon_char_append(file,".ini");
            if (access(file,0)!=F_OK){
                char *command_creation = ubconfig_file_create(file);
                struct passwd *user = getpwnam(yon_ubl_root_user_get());
                int a = system(command_creation);
                if (chown(file,user->pw_uid,user->pw_gid)){};
                free(command_creation);
                if (access(file,0)!=F_OK){
                    yon_ubl_status_box_render(CUSTOM_CONFIG_CREATION_ERROR_LABEL,BACKGROUND_IMAGE_FAIL_TYPE);
                    return NULL;
                }
            }
        }
        char *path = yon_char_unite("'",file,"'",NULL);
        free(file);
        gtk_widget_destroy(dialog->Window);
        return path;
    }

    return NULL;
}

/*
    ===========================================================
                            init section
    ===========================================================
*/

void on_save_parameters(GtkWidget *self, template_saving_window *window){
    yon_ubl_status_box_render(yon_char_get_localised_from_lib(SAVE_PROCESS_LABEL),BACKGROUND_IMAGE_INFO_TYPE);

    int saved_size;
    struct loaded_config *saved_parameters = yon_save_window_get_saved_parameters(window);
    
    int size=0;
    config_str commands = yon_loaded_config_convert_to_save_command(saved_parameters,&size,window->type!=YON_CONFIG_CUSTOM? yon_config_get_type_path(window->type):window->custom_save_path);
    yon_config_parameter_prepare_elements(commands,&size);
    
    char *final_command = yon_char_parsed_to_string(commands,size," ");
    char *new_str_closed = yon_char_replace(final_command,"\n","\\n");

    if (presave_function)
    {
        struct presave_info *data = malloc(sizeof(struct presave_info));
        data->presave_argument = save_success_argument;
        data->save_path = yon_config_command_get_path(new_str_closed);
        _yon_presave_function_start(data);
    } 
        pthread_t thread_id;
        pthread_create(&thread_id, NULL, (void *)_yon_saving_threaded,new_str_closed);

    yon_window_config_custom_window_set(GTK_WINDOW(window->Window),"SaveWindow");
    on_subwindow_close(self);
}

template_debug_window *template_debugger_window_new(){
    template_debug_window *window = malloc(sizeof(template_debug_window));
    GtkBuilder *builder = gtk_builder_new_from_resource(ui_glade_path_debug);
    window->Window=yon_gtk_builder_get_widget(builder,"Window");
    window->HeaderTopic=yon_gtk_builder_get_widget(builder,"HeaderTopic");
    window->HeaderImage=yon_gtk_builder_get_widget(builder,"HeaderImage");
    window->StatusBox=yon_gtk_builder_get_widget(builder,"StatusBox");
    window->Vte=yon_gtk_builder_get_widget(builder,"DebuggerTerminal");
    gtk_window_set_title(GTK_WINDOW(window->Window),template_app_information.app_title);
    gtk_label_set_text(GTK_LABEL(window->HeaderTopic),template_app_information.app_title);
    gtk_window_set_icon_name(GTK_WINDOW(window->Window),yon_char_append("com.ublinux.",template_app_information.app_tech_name));
        gtk_image_set_from_pixbuf(GTK_IMAGE(window->HeaderImage),gtk_icon_theme_load_icon_for_scale(gtk_icon_theme_get_default(),yon_char_append("com.ublinux.",template_app_information.app_tech_name),32,1,GTK_ICON_LOOKUP_FORCE_SIZE,NULL));
    
        yon_window_config_custom_window_setup(GTK_WINDOW(window->Window),"DebugWindow");
    return window;
}

template_saving_window *yon_save_proceed(char *path,YON_CONFIG_TYPE type, ...){
        template_app_information = yon_ubl_get_app_info();
    char *config_to_save = NULL;
    config_to_save = yon_config_get_type_path(type);

    if (!path&&type == YON_CONFIG_CUSTOM){
        path = yon_custom_config_init(GTK_FILE_CHOOSER_ACTION_SAVE);
        if (!path) return NULL;
        if ((access(path,0)==F_OK&&access(path,4)!=F_OK)){
            if (yon_status_box_is_set()){
                yon_ubl_status_box_render(ACCESS_DENIED_LABEL(path),BACKGROUND_IMAGE_FAIL_TYPE);
            }
        }
    } 

    va_list args;
    struct loaded_config *config_compare=NULL;

    va_start(args,type);
    char *compare_command = yon_get_compare_config_command(args,path,type);
    config_compare = yon_config_get_compared(compare_command); // get compare config
    
    template_saving_window *window = yon_saving_window_new();
    yon_save_window_set_status(window,path,type);

    int current_size=0;
    config_str current_config = yon_config_get_all(&current_size); // get INTERNAL config

    struct loaded_config *current_loaded = yon_config_convert_parameter(current_config,current_size); // convert INTERNAL config into struct

    yon_save_window_loaded_config_init(window,current_loaded,config_compare);
    yon_save_window_compared_config_init_unfound(window,current_loaded,config_compare);
    
    if (!yon_save_window_destroy_if_empty(window))
        return NULL;
        
    gtk_tree_view_set_model(GTK_TREE_VIEW(window->ParametersTree),GTK_TREE_MODEL(window->list));
    gtk_widget_show(window->Window);
    on_save_window_parameter_switched(NULL,NULL,window);
    return window;
}

//-------------------------

template_saving_window *yon_exit_window_new(){
    template_saving_window *window = yon_saving_window_new();
    yon_ubl_status_box_spawn(GTK_CONTAINER(window->StatusBox),UNSAVED_LABEL,0,BACKGROUND_IMAGE_FAIL_TYPE);
    gtk_button_set_label(GTK_BUTTON(window->SaveButton),EXIT_LABEL);
    g_signal_handlers_disconnect_by_func(G_OBJECT(window->SaveButton), G_CALLBACK(on_save_parameters),window);
    g_signal_handlers_disconnect_by_func(G_OBJECT(window->ToggleCell), G_CALLBACK(on_save_window_parameter_switched),window);
    g_signal_connect(G_OBJECT(window->SaveButton),"clicked",G_CALLBACK(gtk_main_quit),NULL);

    struct loaded_config *config_compare=NULL;
    config_compare = yon_config_get_compared(yon_config_get_last_command()); // get compare config
    
    int current_size=0;
    config_str current_config = yon_config_get_all(&current_size); // get INTERNAL config

    struct loaded_config *current_loaded = yon_config_convert_parameter(current_config,current_size); // convert INTERNAL config into struct

    yon_save_window_loaded_config_init(window,current_loaded,config_compare);
    yon_save_window_compared_config_init_unfound(window,current_loaded,config_compare);
    
    if (!yon_save_window_destroy_if_empty(window))
        return NULL;
      
    gtk_tree_view_remove_column(GTK_TREE_VIEW(window->ParametersTree),gtk_tree_view_get_column(GTK_TREE_VIEW(window->ParametersTree),0));
    return window;
}

GtkWidget *yon_config_save_window_new(){
    GtkWidget *dialog = gtk_file_chooser_dialog_new(template_app_information.app_title,NULL,GTK_FILE_CHOOSER_ACTION_SAVE,CANCEL_LABEL,GTK_RESPONSE_CANCEL,OPEN_LABEL,GTK_RESPONSE_ACCEPT,NULL);
    gtk_window_set_icon_name(GTK_WINDOW(dialog),template_app_information.app_tech_name);
    gtk_window_set_title(GTK_WINDOW(dialog),template_app_information.app_title);
    gtk_widget_show(dialog);
        GtkFileFilter *filter = gtk_file_filter_new();
		gtk_file_filter_add_pattern(filter,"*.ini");
        gtk_file_filter_set_name(filter, "*.ini");
		gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog),filter);
        GtkFileFilter *filter_json = gtk_file_filter_new();
		gtk_file_filter_add_pattern(filter_json,"*.json");
        gtk_file_filter_set_name(filter_json, "*.json");
		gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog),filter_json);
        GtkFileFilter *filter_yaml = gtk_file_filter_new();
		gtk_file_filter_add_pattern(filter_yaml,"*.yaml");
        gtk_file_filter_set_name(filter_yaml, "*.yaml");
		gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog),filter_yaml);
    return dialog;
}