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

#define _(String) gettext(String)

#define glade_path "/com/ublinux/ui/upac-gtk.glade"
#define CssPath "/com/ublinux/css/upac-gtk.css"
#define config_path yon_char_unite(yon_ubl_user_get_home_directory(),"/.config/",LocaleName,"/",LocaleName,".conf",NULL)
#define icon_path "com.ublinux.upac-gtk"
#define active_icon_path "com.ublinux.libublsettingsui-gtk3.active-symbolic"
#define inactive_icon_path "com.ublinux.libublsettingsui-gtk3.inactive-symbolic"
#define groups_list_path "resource:///com/ublinux/csv/groups-list.csv"
#define desktop_path "resource://com/ublinux/csv/desktop-list.csv"
#define glade_path_os_row "/com/ublinux/ui/upac-gtk-os-row.glade"
#define glade_path_pacman "/com/ublinux/ui/upac-gtk-pacman.glade"
#define glade_path_desktop "/com/ublinux/ui/upac-gtk-desktop.glade"
#define glade_path_package_info "/com/ublinux/ui/upac-gtk-info.glade"

#define LocaleName "upac-gtk"

#define pacman_lock_path "/var/lib/pacman/db.lck"
#define pacman_lock_dir_path "/var/lib/pacman/"
#define yon_check_database_command "pacman -Syy >/dev/null"

#define config_get_command(target) yon_char_unite("ubconfig --source ",target," get system PARAMETERS",NULL)
#define config_get_default_command ""

#define config_get_global_only_parameters ""
#define config_get_local_only_parameters ""

#define PARAMETER_parameter "PARAMETER"
#define PARAMETER_parameter_command "ubconfig --source global get system PARAMETER"

#define ubur_get_command "upac ubur list --csv"

#define install_command(packages) yon_char_unite("upac pacman -S --noconfirm ",packages,NULL)
#define remove_command(packages) yon_char_unite("upac pacman -R --noconfirm ",packages,NULL)
#define ubur_install_command(packages) yon_char_unite("upac ubur reinstall --no-confirm ",packages,NULL)
#define pacman_unlock_database_command yon_debug_output("%s\n","rm -f /var/lib/pacman/db.lck")

typedef char* string;

__attribute__((unused)) static \
string version_application;

enum YON_PAGES{
    YON_PAGE_GROUPS,
    YON_PAGE_MODULES,
    YON_PAGE_PACKAGES,
    YON_PAGE_UBUR,
    YON_PAGE_DESKTOP
};

typedef struct {
    template_config_fields
    int save_config;
    config_str launch_arguments;
    int launch_size;
    GHashTable *pacman_table;
    int pacman_finished;
    int ubur_finished;

    GMutex progress_mutex;
    int progress_active;
} config;

extern config main_config;

typedef struct {
    template_window_fields
    
    GtkWidget *MainOverlay;
    GtkWidget *MainNotebook;
    GtkWidget *InstallButton;

    GtkWidget *MainRepoStatusBox;
    GtkWidget *PackagesStatusImage;
    GtkWidget *PackagesStatusSpinner;
    GtkWidget *PackagesStatusLabel;
    GtkWidget *PackagesStatusButton;

    GtkWidget *GroupsRepoStatusBox;
    GtkWidget *ModulesRepoStatusBox;
    GtkWidget *PackagesRepoStatusBox;
    GtkWidget *DesktopRepoStatusBox;

    GtkWidget *PackagesTree;
    GtkCellRenderer *PackagesChosenCell;
    
    GtkWidget *AdditionalComponentsList;
    
    GtkListStore *PacmanList;
    GtkWidget *PacmanTree;
    GtkWidget *PacmanSearchEntry;
    GtkWidget *PacmanChosenButton;
    GtkCellRenderer *PacmanChosenCell;
    GtkTreeModel *PacmanFilter;

    GtkWidget *UburComponentsList;
    GtkWidget *UburRepoStatusBox;
    GtkWidget *UburSourceLabel;
    GtkWidget *UburSourceButton;

    GtkWidget *DesktopFlow;

    GtkWidget *UncheckAllCheck;
    GtkWidget *OverallSizeLabel;

    GtkWidget *TerminalBox;
    GtkWidget *TerminalProgress;
    GtkWidget *TerminalCancelButton;
    GtkWidget *TerminalMoreButton;
    GtkWidget *TerminalRevealer;
    GtkWidget *InstallTerminal;
    GtkWidget *SizeHandleEvent;
	GFileMonitor *db_lock_monitor;

    GtkTreeStore *PackagesList;
} main_window;

typedef struct
{
	GtkWidget *row;
	GtkWidget *RowBox;
	GtkWidget *InstallCheck;
	GtkWidget *NameLabel;
	GtkWidget *DescriptionLabel;
	GtkWidget *VersionLabel;
	GtkWidget *TagsBox;
	GtkWidget *SourceLabel;
	GtkWidget *SizeLabel;
	GtkWidget *InstallCheckOverlay;

	char *name;
	char *source;
	char *modules;
	char *version;
	char *tags;
	char *description;
	unsigned long size_raw;

    gboolean installed;
    gboolean initially_installed;

} os_row;

struct row_data
{
	main_window *widgets;
	char *version;
	char *name;
	char *tags;
	char *description;
	char *source;
	char *size;
	unsigned long size_raw;
};

typedef struct {
    GtkWidget *Window;
    GtkWidget *StatusBox;
    GtkWidget *PacmanTree;
    GtkCellRenderer *PacmanChosenCell;
    GtkTreeModel *filter;
} yon_pacman_chosen_window;

struct pacman_struct {
    main_window *widgets;
    char *package;
};
typedef struct {
    GtkWidget *MainChild;
    GtkWidget *InstallCheck;
    GtkWidget *NameLabel;
    GtkWidget *AboutButton;
    GtkWidget *ScrollRightEventBox;
    GtkWidget *ScrollLeftEventBox;
    GtkWidget *ArrowsOverlay;
    GtkWidget *MainImage;
    GtkWidget *PrevInstallationSliderImage;
    GtkWidget *NextInstallationSliderImage;
    
    char *name;
    char *package;
    int image_size;
    config_str image_paths;
    int current_image;
    gboolean initially_installed;
} desktop_struct;

void on_save_done(main_window *, config_str output, int size);
void on_config_global_local_save(GtkWidget *, main_window *);
void on_config_local_save(GtkWidget *, main_window *);
void on_config_global_save(GtkWidget *, main_window *);
void on_config_custom_save(GtkWidget *, main_window *);
void on_config_local_load(GtkWidget *,main_window *);
void on_config_global_load(GtkWidget *,main_window *);
void on_config_custom_load(GtkWidget *,main_window *);

void yon_load_proceed(YON_CONFIG_TYPE type);

gboolean yon_interface_update(main_window *);

void config_init();

main_window *yon_main_window_complete(main_window *widgets);
gboolean on_page_switch(GtkWidget *, GtkWidget *, int page,main_window *widgets);
void yon_db_unlock_update(GFileMonitor *,GFile *,GFile *,GFileMonitorEvent ,main_window *widgets);
void yon_update_page(main_window *widgets);
void *yon_db_update(main_window *widgets);
void on_status_button_update(GtkWidget *, main_window *widgets);
void *yon_status_thread_update(main_window *widgets);
void on_status_update(GtkWidget *,main_window *widgets);
void yon_db_lock_update(GFileMonitor *,GFile *,GFile *,GFileMonitorEvent ,main_window *widgets);
void yon_status_thread_update_inactive(main_window *widgets);
void yon_status_thread_update_active(main_window *widgets);
void on_paned_position_changed(GtkWidget *, GdkEvent*,main_window *widgets);
void on_more_clicked(GtkWidget *, main_window *widgets);
GtkTreeIter *yon_groups_category_check(GtkTreeStore *target,char *category);
GtkTreeIter *yon_groups_subcategory_check(GtkTreeStore *target, GtkTreeIter *parent_iter, char *category);
void yon_groups_remove_empty_groups(main_window *widgets);
void yon_groups_tab_init(main_window *widgets);
yon_window *yon_package_info_window_create(const char *package_str);
gboolean on_os_components_info(GtkWidget *, GdkEventButton *, os_row *row);
os_row *yon_module_row_new();
void yon_module_init(main_window *widgets);
gboolean yon_module_insert(struct row_data *row_input);
void yon_module_row_setup(os_row *row, char *name, char *version,char *tags, char *description,char *source, char *size);
guint yon_check_packages_size(main_window *widgets);
guint yon_group_get_size(main_window *widgets);
guint yon_software_get_size(main_window *widgets);
void yon_config_init();
void *yon_pacman_fill(main_window *widgets);
char *yon_size_get_name_from_letter(char letter);
void on_filter_changed(GtkWidget *, main_window *widgets);
gboolean yon_filter(GtkTreeModel* model, GtkTreeIter *iter, main_window *widgets);
void on_pacman_toggled(GtkWidget *, char *path, main_window *widgets);
void on_pacman_window_toggled(GtkWidget *, char *path, yon_pacman_chosen_window *window);
yon_pacman_chosen_window *yon_pacman_chosen_window_new();
void on_pacman_open(GtkWidget *,main_window *widgets);
void yon_on_groups_chosen(GtkWidget *, char *path, main_window *widgets);
void on_switch_all_check(GtkWidget *self,main_window *widgets);
int yon_module_check_selected(main_window *widgets);
void yon_switch_all_update(main_window *widgets);
void yon_groups_switch_all(main_window *widgets);
void yon_pacman_switch_all(main_window *widgets);
void yon_modules_switch_all(main_window *widgets);
void yon_groups_switch_all_recursive(main_window *widgets, GtkTreeIter *parent);
gboolean yon_pacman_window_filter(GtkTreeModel* model, GtkTreeIter *iter, main_window *widgets);
void yon_pacman_set_package(struct pacman_struct *pacman_data);
void yon_pacman_pre_fill(main_window *widgets);
void yon_pacman_post_fill(main_window *widgets);
void *yon_ubur_fill(main_window *widgets);
config_str yon_ubur_get_install_packages(int *size, main_window *widgets);
config_str yon_ubur_get_remove_packages(int *size, main_window *widgets);
config_str yon_modules_get_install_packages(int *size, main_window *widgets);
config_str yon_modules_get_remove_packages(int *size, main_window *widgets);
config_str yon_groups_get_install_packages(int *size, main_window *widgets);
config_str yon_groups_get_remove_packages(int *size, main_window *widgets);
config_str yon_pacman_get_install_packages(int *size, main_window *widgets);
config_str yon_pacman_get_remove_packages(int *size, main_window *widgets);
void on_install_activate(GtkWidget *, main_window *widgets);
gboolean on_terminal_drag(GtkWidget *self, GdkEventButton *event, main_window *widgets);
gboolean on_terminal_drag_move(GtkWidget *self, GdkEventMotion *event, main_window *widgets);
void yon_terminal_init(main_window *widgets);
int yon_terminal_check_height(int height, GtkWidget *terminal_area);
void on_window_resize(GtkWidget *, main_window *widgets);
gboolean on_command_execute_success(GtkWidget *,gint status,main_window *widgets);
gboolean on_terminal_check_progress(main_window *widgets);
void on_terminal_cancel(GtkWidget *,main_window *widgets);
void *yon_command_execute_async(char *command,main_window *widgets);
void yon_ubur_switch_all(main_window *widgets);
int yon_ubur_check_selected(main_window *widgets);
long yon_groups_get_size(main_window *widgets);
long yon_modules_get_size(main_window *widgets);
long yon_pacman_get_size(main_window *widgets);
gboolean yon_size_update(main_window *widgets);
void on_ubur_source_clicked(GtkWidget *, main_window *widgets);

void on_desktop_about(GtkWidget *, desktop_struct *desktop);
gboolean on_desktop_image_prev_clicked(GtkWidget *,GdkEvent *, desktop_struct *desktop);
gboolean on_desktop_image_next_clicked(GtkWidget *,GdkEvent *, desktop_struct *desktop);
desktop_struct *yon_desktop_new();
void yon_desktop_init(main_window *widgets);
void yon_desktop_update(desktop_struct *desktop);
gboolean on_install_slider_hover_highlight(GtkWidget *, GdkEvent *, desktop_struct *desktop);
gboolean on_install_slider_hover_highlight_end(GtkWidget *, GdkEvent *, desktop_struct *desktop);;
config_str yon_desktop_get_install_packages(int *size, main_window *widgets);
config_str yon_desktop_get_remove_packages(int *size, main_window *widgets);
long yon_desktop_get_size(main_window *widgets);
void on_desktop_checked(GtkWidget *, main_window *widgets);
yon_window *yon_package_info_window_create(const char *package_str);