#include "ubl-settings-manager.h"

config main_config;

void on_reveal_banner(GtkWidget *, main_window *widgets){
    if (gtk_revealer_get_reveal_child(GTK_REVEALER(widgets->BannerRevealer))){
        gtk_revealer_set_transition_type(GTK_REVEALER(widgets->BannerRevealer),GTK_REVEALER_TRANSITION_TYPE_SLIDE_LEFT);
        gtk_revealer_set_reveal_child(GTK_REVEALER(widgets->BannerRevealer),0);
        gtk_image_set_from_icon_name(GTK_IMAGE(widgets->BannerArrow),arrow_right_icon_path,GTK_ICON_SIZE_BUTTON);
        int banner = 1;
        yon_window_config_add_instant_parameter(hide_banner_parameter,settings_section,&banner,YON_TYPE_BOOLEAN);
    } else {
        gtk_revealer_set_transition_type(GTK_REVEALER(widgets->BannerRevealer),GTK_REVEALER_TRANSITION_TYPE_SLIDE_RIGHT);
        gtk_revealer_set_reveal_child(GTK_REVEALER(widgets->BannerRevealer),1);
        gtk_image_set_from_icon_name(GTK_IMAGE(widgets->BannerArrow),arrow_left_icon_path,GTK_ICON_SIZE_BUTTON);
        int banner = 0;
        yon_window_config_add_instant_parameter(hide_banner_parameter,settings_section,&banner,YON_TYPE_BOOLEAN);
    }
}

void config_init(){
    memset(&main_config,0,sizeof(config));
    main_config.sections=NULL;
    main_config.SettingsSections=NULL;
    main_config.double_click=0;
    main_config.apps_icon_size=56;
    main_config.labelDensity=0;
};

void yon_config_update(){
    if (!yon_window_config_get_parameter(settings_section,double_click_parameter,&main_config.double_click,YON_TYPE_INT)){
        main_config.double_click=0;

    }
    if (!yon_window_config_get_parameter(settings_section,icon_size_parameter,&main_config.apps_icon_size,YON_TYPE_INT)){
        main_config.apps_icon_size=56;
    }

    main_config.themes = g_hash_table_new(g_str_hash,g_str_equal);
    yon_theme_init();
}
void on_back_clicked(GtkWidget *, GtkWidget *socket){
    gtk_widget_destroy(socket);
}

void on_plug_connected(GtkSocket *self, main_window *widgets){
    gtk_widget_show(widgets->BackButton);
    gtk_widget_hide(widgets->SettingsButton);
    g_signal_connect(G_OBJECT(widgets->BackButton),"clicked",G_CALLBACK(on_back_clicked),self);
}

void on_plug_disconnected(GtkSocket *self, main_window *widgets){
    gtk_widget_hide(widgets->BackButton);
    gtk_widget_show(widgets->SettingsButton);
    g_signal_handlers_disconnect_by_func(G_OBJECT(widgets->BackButton),G_CALLBACK(on_back_clicked),self);
}

void yon_app_thread_complete(void *);
void yon_app_thread_complete(void *){
    if (!gtk_widget_get_sensitive(main_config.widgets->current_theme->HideBox)){
        gtk_widget_set_sensitive(main_config.widgets->current_theme->HideBox,1);
    }
}

void *yon_app_start(char *command){
    g_mutex_lock(&main_config.app_thread_mutex);
    main_config.app_thread_active = 1;
    g_mutex_unlock(&main_config.app_thread_mutex);

    yon_launch(command);

    g_mutex_lock(&main_config.app_thread_mutex);
    main_config.app_thread_active=0;
    g_mutex_unlock(&main_config.app_thread_mutex);
    g_idle_add_once((GSourceOnceFunc)yon_app_thread_complete,NULL);
    g_thread_exit(NULL);
}

GtkSocket *yon_sockets_init(GtkBox *socketBox){
    GtkWidget *main_socket = NULL;
    GList *list = gtk_container_get_children(GTK_CONTAINER(main_config.widgets->SaveSocketBox));
    if (list){
        gtk_widget_destroy(list->data);
        g_list_free(list);
    }
    list = gtk_container_get_children(GTK_CONTAINER(main_config.widgets->LoadSocketBox));
    if (list){
        gtk_widget_destroy(list->data);
        g_list_free(list);
    }
    list = gtk_container_get_children(GTK_CONTAINER(socketBox));
    if (list){
        gtk_widget_destroy(list->data);
        g_list_free(list);
    }
    main_socket = gtk_socket_new();
    main_config.widgets->SaveSocket = gtk_socket_new();
    main_config.widgets->LoadSocket = gtk_socket_new();
    gtk_widget_show(main_config.widgets->SaveSocket);
    gtk_widget_show(main_config.widgets->LoadSocket);
    gtk_widget_show(main_socket);
    gtk_box_pack_start(GTK_BOX(socketBox),main_socket,1,1,0);
    gtk_box_pack_start(GTK_BOX(main_config.widgets->SaveSocketBox),main_config.widgets->SaveSocket,0,0,0);
    gtk_box_pack_start(GTK_BOX(main_config.widgets->LoadSocketBox),main_config.widgets->LoadSocket,0,0,0);

    g_signal_connect(G_OBJECT(main_socket),"plug_added",G_CALLBACK(on_plug_connected),main_config.widgets);
    g_signal_connect(G_OBJECT(main_config.widgets->SaveSocket),"plug-removed",G_CALLBACK(on_plug_disconnect_process),main_config.widgets);
    g_signal_connect(G_OBJECT(main_config.widgets->LoadSocket),"plug-removed",G_CALLBACK(on_plug_disconnect_process),main_config.widgets);
    g_signal_connect(G_OBJECT(main_socket),"destroy",G_CALLBACK(on_plug_disconnected),main_config.widgets);
    return GTK_SOCKET(main_socket);
}

char *yon_get_save_socket(){
    long socket_id = (guint)gtk_socket_get_id(GTK_SOCKET(main_config.widgets->SaveSocket));
    if (socket_id){
        return yon_char_from_long(socket_id);
    }
    return NULL;
}

char *yon_get_load_socket(){
    long socket_id = (guint)gtk_socket_get_id(GTK_SOCKET(main_config.widgets->LoadSocket));
    if (socket_id){
        return yon_char_from_long(socket_id);
    }
    return NULL;
}

// void confugure_setings_window(main_window *widgets){

// }

void yon_interface_update(main_window *widgets){
    if (main_config.sections) {
        yon_dictionary_free_all(main_config.sections,free);
        main_config.sections = NULL;
    }

    gsize size;
    config_str section_settings = yon_window_config_get_section(sections_section,&size);

    if (size){
        for (gsize i=0;i<size;i++){
            app_section *cur_section = yon_app_section_new();
            cur_section->name = yon_char_new(section_settings[i]);
            char *categories = NULL;
            yon_window_config_get_parameter(sections_section,cur_section->name,&categories,YON_TYPE_STRING);
            cur_section->categories = yon_char_parse(categories,&cur_section->categories_size,";");
            yon_dictionary_add_or_create_if_exists_with_data(main_config.sections,cur_section->name,cur_section);
        }
    } else {
        {
            app_section *cur_section = yon_app_section_new();
            cur_section->name = yon_char_new(_("Personal"));
            cur_section->categories = yon_char_parse("X-UBL-SettingsManager;X-UBL-PersonalSettings;",&cur_section->categories_size,";");
            yon_dictionary_add_or_create_if_exists_with_data(main_config.sections,cur_section->name,cur_section);
        }
        {
            app_section *cur_section = yon_app_section_new();
            cur_section->name = yon_char_new(_("Hardware"));
            cur_section->categories = yon_char_parse("X-UBL-SettingsManager;X-UBL-HardwareSettings;",&cur_section->categories_size,";");
            yon_dictionary_add_or_create_if_exists_with_data(main_config.sections,cur_section->name,cur_section);
        }
        {
            app_section *cur_section = yon_app_section_new();
            cur_section->name = yon_char_new(_("System"));
            cur_section->categories = yon_char_parse("X-UBL-SettingsManager;X-UBL-SystemSettings;",&cur_section->categories_size,";");
            yon_dictionary_add_or_create_if_exists_with_data(main_config.sections,cur_section->name,cur_section);
        }
        {
            app_section *cur_section = yon_app_section_new();
            cur_section->name = yon_char_new(_("Misc"));
            cur_section->categories = yon_char_parsed_new(&cur_section->categories_size,"X-UBL-SettingsManager",NULL);
            yon_dictionary_add_or_create_if_exists_with_data(main_config.sections,cur_section->name,cur_section);
        }
    }

    widgets->current_theme = yon_theme_update(widgets);

    widgets->current_theme->list_update_func(widgets->current_theme);
}

char *yon_get_launch_command(const char *application){
    char *command_args = NULL; 
    apps *cur_app = yon_apps_get((char*)application);
    char *env = NULL;
    if (!cur_app) return NULL;
    
    int sockets_allow = yon_environment_get_env_for_launch(&env);
    if (sockets_allow&&!main_config.disable_socket){
        if (cur_app->DualPluggable==1){
            char *save_socket = yon_get_save_socket();
            char *load_socket = yon_get_load_socket();
            char *main_socket_id = yon_get_main_socket();
            command_args = launch_args_command(main_socket_id,load_socket,save_socket);

        } else if (cur_app->Pluggable){
            char *main_socket_id = yon_get_main_socket();
            command_args = yon_char_unite("--socket-id=",main_socket_id,NULL);
        }
    }
    
    if (main_config.debug_mode){
        char *tmp = yon_char_unite("-d ", command_args,NULL);
        if(!yon_char_is_empty(command_args)) free(command_args);
        command_args=tmp;
    }
    char *final_command = yon_char_unite(yon_char_return_if_exist(env,""), !yon_char_is_empty(env)?" ":"", cur_app->Exec, " ", command_args,NULL);
    return final_command;
}


char *yon_get_main_socket(){
    GList *list = gtk_container_get_children(GTK_CONTAINER(main_config.widgets->current_theme->SocketBox));
    long socket_id = (guint)gtk_socket_get_id(GTK_SOCKET(list->data));
    g_list_free(list);
    if (socket_id){
        return yon_char_from_long(socket_id);
    }
    return NULL;
}

void on_main_exit(GtkWidget *, GdkEvent *, main_window *){
    yon_window_config_erase_instant_parameter("file",yon_configuration_window_section);
    gtk_main_quit();
}

gboolean on_plug_disconnect_process(GtkWidget *,main_window *widgets){
    g_mutex_lock(&main_config.app_thread_mutex);
    int active = main_config.app_thread_active;
    g_mutex_unlock(&main_config.app_thread_mutex);
    if (!active){
        return 0;
    }
    return 1;
}

main_window *yon_main_window_setup(){
    main_window *widgets = malloc(sizeof(main_window));
    main_config.widgets=widgets;

    GtkBuilder *builder = gtk_builder_new_from_resource(glade_path);
    widgets->Window = yon_gtk_builder_get_widget(builder,"MainWindow");
    widgets->StatusBox = yon_gtk_builder_get_widget(builder,"StatusBox");
    widgets->TitleLabel = yon_gtk_builder_get_widget(builder,"TitleLabel");
    widgets->ThemeBox = yon_gtk_builder_get_widget(builder,"ThemeBox");
    widgets->SocketBox = yon_gtk_builder_get_widget(builder,"SocketBox");
    widgets->BackButton = yon_gtk_builder_get_widget(builder,"BackButton");
    widgets->SettingsButton = yon_gtk_builder_get_widget(builder,"SettingsButton");
    widgets->BannerImage = yon_gtk_builder_get_widget(builder,"BannerImage");
    widgets->BannerRevealer = yon_gtk_builder_get_widget(builder,"BannerRevealer");
    widgets->BannerButton = yon_gtk_builder_get_widget(builder,"BannerButton");
    widgets->BannerArrow = yon_gtk_builder_get_widget(builder,"BannerArrow");
    widgets->SaveSocketBox = yon_gtk_builder_get_widget(builder,"SaveSocketBox");
    widgets->LoadSocketBox = yon_gtk_builder_get_widget(builder,"LoadSocketBox");

    widgets->MainMenuItemSettings = yon_gtk_builder_get_widget(builder,"MainMenuItemSettings");
    widgets->MainMenuItemAbout = yon_gtk_builder_get_widget(builder,"MainMenuItemAbout");
    widgets->MainMenuItemDocumentation = yon_gtk_builder_get_widget(builder,"MainMenuItemDocumentation");

    yon_gtk_window_setup(GTK_WINDOW(widgets->Window),NULL,TITLE_LABEL,icon_path,NULL);
    yon_apps_init();

    g_signal_connect(G_OBJECT(widgets->Window),"delete-event",G_CALLBACK(on_main_exit),widgets);
    g_signal_connect(G_OBJECT(widgets->MainMenuItemSettings),"activate",G_CALLBACK(on_settings_open),widgets);
    g_signal_connect(G_OBJECT(widgets->BannerButton),"clicked",G_CALLBACK(on_reveal_banner),widgets);
    g_signal_connect(G_OBJECT(widgets->MainMenuItemDocumentation),"activate",G_CALLBACK(on_open_documentation_confirmation),WIKI_LINK);
    g_signal_connect(G_OBJECT(widgets->MainMenuItemAbout),"activate",G_CALLBACK(on_about),version_application);

    
    yon_window_config_setup(GTK_WINDOW(widgets->Window));
    char *path = yon_char_unite(yon_ubl_user_get_home_directory(),"/.config/",LocaleName,"/",LocaleName,".conf",NULL);
    yon_window_config_load(path);

    yon_configuration_window_set_custom_name(CONFIGURATION_MODE_LABEL);
    yon_ubl_settings_window_init(GTK_MENU(gtk_widget_get_parent(widgets->MainMenuItemAbout)));
    yon_configuration_window_set_size(-1,175);
    struct yon_configuration_window_custom_parameter *parameter = malloc(sizeof(struct yon_configuration_window_custom_parameter));
    parameter->custom_parameter_create_func = yon_config_chooser_new;
    parameter->custom_parameter_save_value_func = yon_config_chooser_save;
    parameter->custom_parameter_update_func = yon_config_chooser_update;
    yon_configuration_window_add_custom_parameter("file",parameter);

    free(path);
    yon_config_update();
    {
        int banner_hidden = 0;
        yon_window_config_get_parameter(settings_section,hide_banner_parameter, &banner_hidden,YON_TYPE_BOOLEAN);
        gtk_revealer_set_transition_type(GTK_REVEALER(widgets->BannerRevealer),!banner_hidden?GTK_REVEALER_TRANSITION_TYPE_SLIDE_LEFT:GTK_REVEALER_TRANSITION_TYPE_SLIDE_RIGHT);
        gtk_revealer_set_reveal_child(GTK_REVEALER(widgets->BannerRevealer),!banner_hidden);
        gtk_image_set_from_icon_name(GTK_IMAGE(widgets->BannerArrow),!banner_hidden?arrow_left_icon_path:arrow_right_icon_path,GTK_ICON_SIZE_BUTTON);
    }
    gtk_widget_show(widgets->Window);
    yon_interface_update(widgets);
    return 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);

    static struct option long_options[] = {
            {"lock-settings", 0, 0, 'l'},
            {"help", 0, 0, 'h'},
            {"version", 0, 0, 'v'},
            {"clear-config", 0,0, 'c'}, 
            {"config", 1, 0, 'f'},
            {"debug", 0, 0, 'd'},
            {"disable-gtksocket", 0, 0, 's'},

            {"setenv", 1, 0, 'S'},
            };
    int option_index=0;
    for (int i=0;i<argc;i++){
        int argument = getopt_long(argc,argv,"lhvcdsS",long_options,&option_index);
        switch (argument){
            case 'l':
                main_config.lock_settings=1; 
                break;
            case 'h':
                printf("%s\n",HELP_MANAGER_LABEL);
                exit(0);
                break;
            case 'v':
                printf("%s\n",VERSION_LABEL);
                exit(0);
                break;
            case 'c': char *path = yon_char_unite(yon_ubl_user_get_home_directory(),"/.config/",template_app_information.app_tech_name,"/",NULL);
                struct passwd *user = getpwnam(yon_ubl_root_user_get());
                if (chown(path,user->pw_uid,user->pw_gid)){};
                if (system(remove_config_dir_command)){}; 
                break;
            case 'f':
                main_config.force_ini = yon_char_new(optarg);
                main_config.config_load_path = template_config->force_ini;
                main_config.config_save_path = template_config->force_ini;
            break;
            case 'd':
                main_config.debug_mode=1;
            break;
            case 's':
                main_config.disable_socket=1;
            break;
            case 'S':
                char *parameter = yon_char_new(optarg);
                if (!yon_char_is_empty(parameter)&&strstr(parameter,"=")){
                    char *key = yon_char_divide_search(parameter,"=",-1);
                    setenv(key,parameter,1);
                }
            break;
        }
    }
    if (template_config->debug_mode){
        config_str env = g_get_environ();
        for( int i=0;env[i];i++){
            yon_debug_output("%s\n",env[i]);
        }
    }
    gtk_init(&argc, &argv);
    main_window *widgets = yon_main_window_setup();
    GtkWidget *root_button = yon_root_button_new(argv,argc);
    yon_root_button_init(root_button,GTK_WINDOW(widgets->Window));
    gtk_menu_shell_prepend(GTK_MENU_SHELL(gtk_widget_get_parent(widgets->MainMenuItemDocumentation)),root_button);

    GtkCssProvider *css=gtk_css_provider_new();
    gtk_css_provider_load_from_resource(css,CssPath);
    gtk_style_context_add_provider_for_screen(gdk_screen_get_default(),
                               GTK_STYLE_PROVIDER(css),
                               -1);
    gtk_main();
    
}