#include <gtk/gtk.h>
#include <gtk/gtkx.h>
#include <vte/vte.h>
#include <locale.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <libintl.h>
#include <getopt.h>
#include <libintl.h>
#include <libublsettings.h>
#include <libublsettings-gtk3.h>
#include <libublsettingsui-gtk3.h>
#ifdef WEBKIT_FOUND
    #include <webkit2/webkit2.h>
#endif 
#include "ubl-strings.h"

#define _(String) gettext(String)

#define glade_path "/com/ublinux/ui/ubl-settings-kernel.glade"
#define glade_info_path "/com/ublinux/ui/ubl-settings-kernel-info.glade"
#define glade_install_path "/com/ublinux/ui/ubl-settings-kernel-install.glade"
#define glade_table_row_path "/com/ublinux/ui/ubl-settings-kernel-table-row.glade"
#define glade_additions_table_row_path "/com/ublinux/ui/ubl-settings-kernel-additions-table-row.glade"
#define glade_dialog_path "/com/ublinux/ui/ubl-settings-kernel-dialog.glade"
#define banner_path "/com/ublinux/images/ubl-settings-kernel-banner.png"
#define CssPath "/com/ublinux/css/ubl-settings-kernel.css"
#define config_path yon_char_unite(yon_ubl_user_get_home_directory(),"/.config/",LocaleName,"/",LocaleName,".conf",NULL)

#define kernels_path "resource:///com/ublinux/csv/kernel-list.csv"
#define kernels_addon_path "resource:///com/ublinux/csv/kernel-list-addon.csv"
#define module_icon_path "com.ublinux.libublsettingsui-gtk3.cubes-symbolic"
#define package_icon_path "com.ublinux.libublsettingsui-gtk3.dropbox-symbolic"
#define run_icon_path "com.ublinux.libublsettingsui-gtk3.play-symbolic"
#define restart_icon_path "com.ublinux.libublsettingsui-gtk3.reset-symbolic"

#define LocalePath "/usr/share/locale" 
#define LocaleName "ubl-settings-kernel"

#define icon_path "com.ublinux.ubl-settings-kernel"

#define pacman_unlock_database_command yon_debug_output("%s\n","rm -f /var/lib/pacman/db.lck")

#define get_kernel_changelog_command(target) yon_debug_output("%s\n",yon_char_unite("find /usr/lib/modules/ -maxdepth 2 -type f -iname \"pkgbase\" -exec grep -il \"",target,"\" {} + | xargs dirname | xargs -I {} cat \"{}/changelog\"", NULL))
#define get_package_info_command(target) yon_debug_output("%s\n",yon_char_append("pacman -Si ",target))
#define get_package_is_installed_command(target) yon_debug_output("%s\n",yon_char_append("pacman -Qq ",target))

#define install_command(target) yon_debug_output("%s\n",yon_char_append("pacman -Sy --noconfirm ",target))
#define remove_command(target) yon_debug_output("%s\n",yon_char_append("pacman -R --noconfirm ",target))
#define get_dependent_command(target) yon_debug_output("%s\n",yon_char_append("pactree -rl ",target))
#define check_pactree_exist_command yon_debug_output("%s\n","which pactree > /dev/null 2>&1")
#define yon_check_database_command yon_debug_output("%s\n","pacman -Sqs >/dev/null")

#define pacman_update_command yon_debug_output("%s\n","pacsync --updated")

#define get_active_kernel_command yon_debug_output("%s\n","cat /usr/lib/modules/$(uname -r)/pkgbase")

#define build_command_basic(target,kernel, only) yon_debug_output("%s\n",yon_char_unite("ubmkuird -l",!yon_char_is_empty(target)?" -n ":"",!yon_char_is_empty(target)?target:"",!yon_char_is_empty(kernel)?" -k ":"",!yon_char_is_empty(kernel)?kernel:"", only? " -H ":"",NULL))
#define build_command_debug(target,kernel) yon_debug_output("%s\n",yon_char_unite("ubmkuird -l --addon",!yon_char_is_empty(target)?" -n ":"",!yon_char_is_empty(target)?target:"",!yon_char_is_empty(kernel)?" -k ":"",!yon_char_is_empty(kernel)?kernel:"",NULL))
#define build_command_universal(target,kernel) yon_debug_output("%s\n",yon_char_unite("ubmkuird -l --kmod",!yon_char_is_empty(target)?" -n ":"",!yon_char_is_empty(target)?target:"",!yon_char_is_empty(kernel)?" -k ":"",!yon_char_is_empty(kernel)?kernel:"",NULL))

#define yon_config_get_custom_command(target) yon_debug_output("%s\n",yon_char_unite("ubconfig --source ",target," get boot KERNEL_BOOT",NULL))
#define config_get_local_command "ubconfig --source system get boot KERNEL_BOOT"
#define config_get_global_command "ubconfig --source global get boot KERNEL_BOOT"
#define config_get_default_command "ubconfig --source default get boot KERNEL_BOOT"

#define config_get_global_only_parameters ""
#define config_get_local_only_parameters ""

#define KERNEL_BOOT_parameter "KERNEL_BOOT"
#define KERNEL_BOOT_command "ubconfig --source global get boot KERNEL_BOOT"

typedef char* string;
string version_application;

char *local;

enum ACTION_TYPE{
    ACTION_LOAD,
    ACTION_SAVE,
    ACTION_TERMINAL_EXECUTE_SUCCESS,
    ACTION_TERMINAL_EXECUTE_FAIL
};

typedef struct {
    template_config_fields
    GMutex mutex;
    int save_config;
    dictionary *kernel_tabs;
    dictionary *addition_tabs;
    GMutex progress_mutex;
    int progress_active;
    config_str launch_arguments;
    int launch_size;
    enum ACTION_TYPE action;

    char *local_load_success_localised;
    char *global_load_success_localised;

    int update_active;
    GMutex update_mutex;
} config;

typedef struct {
    template_window_fields
    GtkWidget *UpdateButton;
    GtkWidget *BuildingButton;
    GtkWidget *UnlockPacmanButton;
    GtkWidget *KernelsUpperTree;
    GtkWidget *KernelsTree;
    GtkWidget *AdditionsUpperTree;
    GtkWidget *AdditionsTree;
    GtkWidget *MainNotebook;
    GtkWidget *KernelsPackageBox;
    GtkWidget *AdditionsPackageBox;

    GtkListStore *KernelsList;
    GtkListStore *AdditionsList;

    GtkSizeGroup *StatusSizeGroup;
    GtkSizeGroup *KernelSizeGroup;
    GtkSizeGroup *TagsSizeGroup;
    GtkSizeGroup *InstallSizeGroup;
    GtkSizeGroup *RunSizeGroup;
    GtkSizeGroup *DescriptionSizeGroup;
    GtkSizeGroup *ButtonsSizeGroup;

    GtkWidget *MainRevealer;
    GtkWidget *TerminalRevealer;
    GtkWidget *InstallTerminal;
    GtkWidget *InstallationProgress;
    GtkWidget *CancelButton;
    GtkWidget *MoreButton;
    GtkWidget *TerminalPaned;
    GtkWidget *TerminalScroll;

    GtkWidget *MainOverlay;
    GtkWidget *MainOverlayBox;
    GtkWidget *LoadingSpinner;
} main_window;


typedef struct {
    GtkWidget *window;
    GtkWidget *HeadLabel;
    GtkWidget *InfoLabel;
}info_window;

typedef struct {
    GtkWidget *window;
    GtkWidget *HeadLabel;
    GtkWidget *StatusBox;

    GtkWidget *CancelButton;
    GtkWidget *ExecuteButton;

    GtkWidget *KernelVersionCombo;
    GtkWidget *FilenameEntry;
    GtkWidget *BasicSwitch;
    GtkWidget *BasicCurrentSwitch;
    GtkWidget *DebugSwitch;
    GtkWidget *UniversalSwitch;
    GtkWidget *BackgroundFrame;
    GtkWidget *ShowRevealer;
    GtkWidget *ArrowButton;
}install_window;

typedef struct {
    char *module;
    char *package;
    char *name;
    int module_installed;
    int package_installed;
    int module_updated;
    int package_updated;
    GtkWidget *main_box;
    GtkWidget *name_label;
    GtkWidget *module_label;
    GtkWidget *package_label;
    GtkWidget *module_icon;
    GtkWidget *package_icon;
    GtkWidget *install_tags_box;
    GtkWidget *description_label;
    GtkWidget *remove_module_button;
    GtkWidget *remove_package_button;
    GtkWidget *update_module_button;
    GtkWidget *update_package_button;
    GtkWidget *install_module_button;
    GtkWidget *install_package_button;
    GtkWidget *changelog_button;
    GtkWidget *launch_button;
    GtkWidget *run_tags_box;
    GtkWidget *tags_box;
    config_str module_requirements;
    int module_requirements_size;
    config_str package_requirements;
    int package_requirements_size;

} kernels_tab;

typedef struct {
    char *module;
    char *package;
    char *name;
    int module_installed;
    int package_installed;
    int module_updated;
    int package_updated;
    GtkWidget *main_box;
    GtkWidget *name_label;
    GtkWidget *module_label;
    GtkWidget *package_label;
    GtkWidget *module_icon;
    GtkWidget *package_icon;
    GtkWidget *install_tags_box;
    GtkWidget *description_label;
    GtkWidget *remove_module_button;
    GtkWidget *remove_package_button;
    GtkWidget *update_module_button;
    GtkWidget *update_package_button;
    GtkWidget *install_module_button;
    GtkWidget *install_package_button;
    GtkWidget *changelog_button;
    GtkWidget *launch_button;
    GtkWidget *run_tags_box;
    GtkWidget *tags_box;

} additions_kernels_tab;

typedef struct {
    GtkWidget *Window;
    GtkWidget *HeadLabel;
    GtkWidget *TopicLabel;
    GtkWidget *DependencesTree;
    GtkWidget *CancelButton;
    GtkWidget *AcceptButton;
    GtkWidget *DependencesFrame;
    GtkCellRenderer *ChooseCell;
    GtkListStore *liststore1;

} dialog_window;

void on_save_done(main_window *widgets, config_str output, int size);

char *yon_package_string_set(char *target);
gboolean yon_tab_create_tags(kernels_tab *tab);
void yon_tab_set_installed(kernels_tab *tab);
void *yon_interface_update(main_window *widgets);


void on_config_save(GtkWidget *self, main_window *widgets);
void on_config_global_save(GtkWidget *self, main_window *widgets);
void on_config_local_save(GtkWidget *self, main_window *widgets);
void on_config_custom_save(GtkWidget *self, main_window *widgets);

void yon_load_proceed(YON_CONFIG_TYPE type);

void on_config_local_load(GtkWidget *, main_window *widgets);
void on_config_global_load(GtkWidget *, main_window *widgets);
void on_config_custom_load(GtkWidget *,main_window *widgets);

char *yon_package_dependent_get(char *target);

void on_terminal_done(GtkWidget *, int state, GtkWidget *status_box);
void yon_terminal_window_start(GtkWindow *parent_window, char *command);

void config_init();

void yon_main_window_complete(main_window *widgets);

gboolean on_command_execute_success(GtkWidget *,gint,main_window *widgets);
gboolean yon_terminal_get_progress(main_window *widgets);
void *yon_command_execute_async(char *command,main_window *widgets);

dialog_window *yon_dialog_window_new();

void on_module_install_accept(GtkWidget *, dictionary *dict);
void on_package_install_accept(GtkWidget *, dictionary *dict);
void on_module_remove_accept(GtkWidget *, dictionary *dict);
void on_package_remove_accept(GtkWidget *, dictionary *dict);

void on_module_remove_done(GtkWidget *self, int state, kernels_tab *tab);
void on_module_install_clicked(GtkWidget *,dictionary *dict);
void on_package_install_clicked(GtkWidget *,dictionary *dict);
void on_module_remove_clicked(GtkWidget *,dictionary *dict);
void on_package_remove_clicked(GtkWidget *,dictionary *dict);
void on_launch_cliked(GtkWidget *,dictionary *dict);

int yon_tag_add(GtkBox *target,char *tag_label, char *tag_style, char *icon_name);
kernels_tab *yon_tab_row_new(GtkListBox *target, char *target_string, main_window *widgets);
additions_kernels_tab *yon_additions_tab_row_new(GtkListBox *target, char *target_string, main_window *widgets);

void on_update_clicked(GtkWidget *, main_window *widgets);

void on_selection_changed(GtkWidget *self,GtkListBoxRow* row,main_window *widgets);

void on_info_clicked(GtkWidget *, char *, kernels_tab *tab);

void on_changelog_clicked(GtkWidget *, kernels_tab *tab);

void on_build_selection_changed(GtkWidget *,int,install_window *window);

void on_build_execute(GtkWidget *, dictionary *dict);

void on_building_clicked(GtkWidget *, main_window *widgets);

void on_boot_toggled(GtkWidget *, char *path, main_window *widgets);

void on_terminal_revealer_open(GtkWidget *, main_window *widgets);

void on_basic_toggled(GtkSwitch *self,int state, install_window *window);

info_window *yon_info_window_new();
install_window *yon_install_window_new();

void on_terminal_cancel(GtkWidget *,main_window *widgets);

void on_pacman_db_unlock(void);
void on_paned_position_changed(GtkWidget *, GdkEvent*,main_window *widgets);
gboolean on_terminal_check_progress(main_window *widgets);
void on_database_update(void *,main_window *widgets);