#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 <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-events.glade"
#define glade_path_row "/com/ublinux/ui/ubl-settings-events-row.glade"
#define glade_path_table "/com/ublinux/ui/ubl-settings-events-table.glade"
#define glade_path_insector "/com/ublinux/ui/ubl-settings-events-inspector.glade"
#define glade_path_add "/com/ublinux/ui/ubl-settings-events-add.glade"
#define banner_path "/com/ublinux/images/ubl-settings-events-banner.png"
#define CssPath "/com/ublinux/css/ubl-settings-events.css"
#define config_path yon_char_unite(yon_ubl_user_get_home_directory(),"/.config/",LocaleName,"/",LocaleName,".conf",NULL)
#define audit_desktop_command "/usr/bin/ubl-settings-audit"
#define audit_local_command "/usr/local/bin/ubl-settings-audit"
#define rules_path "resource:///com/ublinux/csv/auditd_rules.csv"
#define commands_path "resource:///com/ublinux/csv/auditd_commands.csv"
#define audit_disable_command "ubconfig set [logging] AUDITD=disable"
#define audit_enable_command "ubconfig set [logging] AUDITD=enable"
#define audit_stop_command "systemctl stop auditd.service"
#define audit_start_command "systemctl start auditd.service"

#define audit_check_enabled_command "ubconfig get logging AUDITD"
#define audit_check_active_command "systemctl status auditd.service --no-pager"

#define add_icon_path "com.ublinux.libublsettingsui-gtk3.increase-symbolic"
#define remove_icon_path "com.ublinux.libublsettingsui-gtk3.trash-symbolic"

#define id_exist_icon_path "com.ublinux.libublsettingsui-gtk3.xmarker-symbolic"
#define id_free_icon_path "com.ublinux.libublsettingsui-gtk3.accept-symbolic"

#define audit_active_icon_path "com.ublinux.ubl-settings-events.active-symbolic"
#define audit_inactive_icon_path "com.ublinux.ubl-settings-events.inactive-symbolic"
#define audit_paused_icon_path "com.ublinux.ubl-settings-events.paused-symbolic"

#define check_audit_status_command "auditctl -s | grep enabled | cut -d' ' -f2 | awk '{if ($1 == 0) {exit 1} else {exit 0}}'"

#define service_start_icon_name "com.ublinux.libublsettingsui-gtk3.play-symbolic"
#define service_stop_icon_name "com.ublinux.libublsettingsui-gtk3.stop-symbolic"

#define service_start_status_icon_name "com.ublinux.libublsettingsui-gtk3.active-symbolic"
#define service_stop_status_icon_name "com.ublinux.libublsettingsui-gtk3.inactive-symbolic"

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

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

#define config_get_command(source) yon_char_unite("ubconfig --source ",source," -ea get [logging] AUDITD AUDITD[*]",NULL)

// #define yon_config_get_custom_command(target) yon_char_unite("ubconfig --source ",target," get logging AUDITD AUDITD[*]",NULL)
#define config_get_local_command "ubconfig --source system -ea get logging AUDITD AUDITD[*]"
#define config_get_global_command "ubconfig --source global -ea get logging AUDITD AUDITD[*]"
#define config_get_default_command ""

#define config_presave_clean_command(target_config) yon_char_unite("ubconfig ",!yon_char_is_empty(target_config)?"--target ":"",!yon_char_is_empty(target_config)?target_config:""," remove logging AUDITD[*]",NULL)

#define config_get_global_only_parameters ""
#define config_get_local_only_parameters ""

#define get_rules_command "auditctl -l"

#define AUDITD_parameter "AUDITD"
#define AUDITD_search "AUDITD["
#define AUDITD_comments_search "AUDITD[comment_"
#define AUDITD(target) yon_char_unite("AUDITD[",target,"]",NULL)
#define AUDITD_cmd(target) yon_char_unite("ubconfig --source global get logging AUDITD[",target,"]",NULL)
#define AUDITD_command "ubconfig --source global get logging AUDITD"

typedef char* string;

__attribute__((unused)) static \
string version_application;

typedef struct {
    template_config_fields
    int save_config;
    config_str launch_arguments;
    int launch_size;

    GtkSizeGroup *IDSizeGroup;
    GtkSizeGroup *RuleSizeGroup;
    GtkSizeGroup *DescriptionSizeGroup;
    GHashTable *trees;
    GSequence *trees_order;
    int comments_size;
} config;

extern config main_config;

typedef struct {
    template_window_fields
    
    GtkWidget *HeaderTree;
    GtkWidget *UpdateButton;
    GtkWidget *AuditExitButton;
    GtkWidget *AuditPauseButton;
    GtkWidget *ListRulesButton;
    GtkWidget *MoveUpButton;
    GtkWidget *MoveDownButton;
    GtkWidget *AddButton;
    GtkWidget *InsertAtButton;
    GtkWidget *RemoveButton;
    GtkWidget *ResetButton;
    GtkWidget *TemplateFillButton;
    GtkWidget *StartAuditButton;
    GtkWidget *TabsBox;
    GtkWidget *AuditStatusImage;
    GtkWidget *LoadingOverlay;
    GtkWidget *LoadingSpinner;
    GtkWidget *CheckLevelBox;
    GtkWidget *IDLabel;
    GtkWidget *RuleLabel;
    GtkWidget *DescriptionLabel;
    GtkWidget *CheckAllButton;
    GtkWidget *UncheckAllButton;
    GtkAdjustment *ScrollAdjustment;

    dictionary *tables;

    rmb_menu_window *rmb_menu;

} main_window;

typedef struct {
    GtkWidget *MainBox;
    GtkWidget *HeadList;
    
    dictionary *items;
} yon_menu_row;

typedef struct {
    GtkWidget *MainBox;
    GtkWidget *MainListBox;

    char *key;
    char *rule;
    char *description;
    int enabled;

    GtkWidget *EnabledCheck;
    GtkWidget *IdLabel;
    GtkWidget *RuleLabel;
    GtkWidget *DescriptionLabel;
    GtkWidget *Separator1;
    GtkWidget *Separator2;
    GtkWidget *Separator3;

    GSequenceIter *order_position;
    
} yon_menu_table;

typedef struct {
    GtkWidget *Window;

    GtkWidget *HatText;
    GtkWidget *HeaderText;
    GtkWidget *InfoText;
    GtkWidget *AlwaysOpenCheck;

    GtkWidget *CloseButton;
    GtkWidget *AcceptButton;
} documentation_confirmation_window;

typedef struct {
    
GtkWidget *MainWindow;
GtkWidget *StatusBox;

GtkWidget *CancelButton;
GtkWidget *SaveButton;
GtkWidget *AutosetButton;
GtkWidget *IDEntry;
GtkWidget *RuleEntry;
GtkWidget *DescriptionTextView;
char *last_description;
} add_window;

typedef struct {

GtkWidget *MainWindow;
GtkWidget *plugBox;
GtkWidget *UpdateButton;
GtkWidget *RulesTerminal;
} inspector_window;

typedef struct {
    GPtrArray *treeviews;
    guint n_columns;
} ColumnSyncData;

typedef struct build_data {
    main_window *widgets;
    config_str current_parameters;
    int current_size;
} build_data;

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 *);

yon_menu_row *yon_menu_get_prev(main_window *widgets, yon_menu_row *tab);
yon_menu_row *yon_menu_get_next(main_window *widgets, yon_menu_row *tab);

gboolean on_selection_block(GtkWidget *, GdkEventButton *,main_window *);
gboolean on_selection_clean(GtkWidget *self, GdkEventButton *,main_window *widgets);

void yon_load_proceed(YON_CONFIG_TYPE type);

void *yon_interface_update(main_window *);

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

void config_init();

void yon_main_window_complete(main_window *widgets);

void yon_menu_tables_save(main_window *widgets);
void yon_interface_save(main_window *widgets);
void on_process_stop_clicked(GtkWidget *,main_window *widgets);
void on_process_pause_clicked(GtkWidget *,main_window *);
void on_inspector_rules_update(GtkWidget *, inspector_window *window);
void on_process_inspect_clicked(GtkWidget *,main_window *widgets);
void on_move_up_clicked(GtkWidget *,main_window *widgets);
void on_move_down_clicked(GtkWidget *,main_window *widgets);
void on_check_clicked(GtkWidget *,main_window *widgets);
void on_uncheck_clicked(GtkWidget *,main_window *widgets);
void on_insert_clicked(GtkWidget *,main_window *widgets);
void on_add_clicked(GtkWidget *,main_window *widgets);
void on_remove_clicked(GtkWidget *,main_window *widgets);
void on_audit_open_clicked(GtkWidget *,main_window *widgets);
yon_menu_row *yon_menu_row_new();
void on_add_accept(GtkWidget *, dictionary *dict);
void on_insert_accept(GtkWidget *, dictionary *dict);
add_window *yon_add_window_new();
yon_menu_row *yon_list_box_get_selected_row(dictionary *list, GtkListBox *listbox);
void on_list_selection_changed(GtkListBox *self, GtkListBoxRow *row, main_window *widgets);
void on_selection_changed(GtkListBox *self, GtkListBoxRow *, main_window *widgets);
yon_menu_table *yon_menu_table_get_selected(GtkListBoxRow *row);
yon_menu_table *yon_menu_table_new();
gboolean yon_sync_columns_idle(gpointer user_data);
void yon_sync_treeview_columns(GPtrArray *treeviews, guint n_columns);
yon_menu_table *yon_menu_table_get_next(main_window *widgets, yon_menu_table *tab);
yon_menu_table *yon_menu_table_get_prev(main_window *widgets, yon_menu_table *tab);
yon_menu_row *yon_menu_row_get_prev(main_window *widgets, yon_menu_row *tab);
yon_menu_row *yon_menu_row_get_next(main_window *widgets, yon_menu_row *tab);
void yon_audit_status_update(main_window *widgets);
void yon_audit_update(main_window *widgets);
void on_audit_control(GtkWidget *, main_window *widgets);
gboolean yon_list_clear(main_window *widgets);
config_str yon_list_get(int *size);
gboolean yon_list_init(build_data *data);
void yon_tables_unselect(void *, void *tabe, void *activatr);
void yon_list_resize(main_window *widgets);
void yon_menu_table_insert(yon_menu_table *table,yon_menu_table *position);
yon_menu_table *yon_menu_table_row_insert(GtkListBox *List, char *key, char *rule, char *description,yon_menu_table *position,main_window *widgets);
void on_autoset_clicked(GtkWidget *,add_window *window);
void on_update_clicked(GtkWidget *, main_window *widgets);
void yon_sequence_save_rules(yon_menu_table *table, void*);
void on_enabled_toggled(GtkWidget *, yon_menu_table *table);
void on_audit_configure(GtkWidget *, main_window *widgets);
void yon_menu_table_destroy(yon_menu_table *table);
void on_reset(GtkWidget *,main_window *widgets);
void on_template_refill(GtkWidget *,main_window *);
void yon_menu_table_update(yon_menu_table *table);
char *yon_id_from_int(int id);
void on_id_check(GtkEntry *self);
void on_description_changed(GtkTextBuffer *self, add_window *window);
void on_enabled_changed(GtkWidget *, GdkEvent*,main_window *widgets);
void on_active_changed(GtkWidget *, GdkEvent*,main_window *widgets);
void on_tabs_select_all(GtkWidget *, main_window *widgets);
void on_tabs_unselect_all(GtkWidget *, main_window *widgets);
void on_tabs_select(GtkWidget *, main_window *widgets);
void on_move_cursor ( GtkListBox* self, GtkMovementStep object, gint p0, main_window *widgets);

void on_check_all_clicked(GtkWidget *,main_window *widgets);
void on_uncheck_all_clicked(GtkWidget *,main_window *widgets);
void on_audit_start_clicked(GtkWidget *, service_window *window);
void on_audit_stop_clicked(GtkWidget *, service_window *window);
void on_audit_update_clicked(GtkWidget *, service_window *window);