#include <gtk/gtk.h>
#include <gtk/gtkx.h>
#include <webkit2/webkit2.h>
#include <vte/vte.h>
#include <locale.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
#include <libintl.h>
#include <sys/types.h>
#include <fcntl.h>
#include <getopt.h>
#include <libintl.h>
#include <time.h>
#include <json-c/json.h>
#include "ubl-strings.h"
#include <libublsettings.h>
#include <libublsettings-gtk3.h>
#include <libublsettingsui-gtk3.h>
#ifndef UBL_SETINGS_VIDEO_H
#define UBL_SETINGS_VIDEO_H

#define HOMEPAGE_LINK _("https://wiki.ublinux.com")

#define icon_name "com.ublinux.ubl-settings-video"

#define glade_path "/com/ublinux/ui/ubl-settings-video.glade"
#define glade_path_driver "/com/ublinux/ui/ubl-settings-video-driver-tab.glade"
#define glade_path_html "/com/ublinux/ui/ubl-settings-video-html.glade"
#define glade_terminal_path "/com/ublinux/ui/ubl-settings-video-terminal.glade"
#define glade_path_monitor "/com/ublinux/ui/ubl-settings-video-monitor.glade"
#define glade_path_configuration "/com/ublinux/ui/ubl-settings-video-configuration.glade"

#define LocalePath "/usr/share/locale"
#define LocaleName "ubl-settings-video"
#define CssPath "/com/ublinux/css/ubl-settings-video.css"
#define html_path(target) yon_char_unite("resource:///com/ublinux/html/",target,".html",NULL)

#define get_ports_command "xrandr |grep -E '.*connected' |cut -d' ' -f1"

#define get_resolutions_and_ports_command "xrandr | awk '\n\
/^Screen / { next }\n\
/^[a-zA-Z]/ {\n\
    if (port != \"\") {\n\
        print port \":\" (res ? res : \"\")\n\
    }\n\
    port = $1\n\
    res = \"\"\n\
    connected = ($2 == \"connected\")\n\
    next\n\
}\n\
/^[[:space:]]+[0-9]+x[0-9]+/ && connected {\n\
    split($1, parts, \"+\")\n\
    mode = parts[1]\n\
    if (!(mode in seen)) {\n\
        seen[mode] = 1\n\
        res = res ? res \",\" mode : mode\n\
    }\n\
}\n\
END {\n\
    if (port != \"\") {\n\
        print port \":\" (res ? res : \"\")\n\
    }\n\
}\
'"

#define table_format_command(target) yon_char_unite("tail +2 <<< '",target,"' | column -t -s';'",NULL)

#define get_resolutions_command "xrandr  |grep -noP \"\\d+x+\\d+\""
#define get_resolution_ports_command "xrandr |grep  -nwP  \"connected\" |grep -oE \"[-0-9a-zA-Z:]{1,} connected\" |grep -oE \"[-0-9a-zA-Z:]{1,} \""

#define get_proprietary_drivers_info_path "resource:///com/ublinux/csv/video-drivers.csv"

#define get_resolutions_supportable_command "resource:///com/ublinux/csv/resolutions.csv"

#define pacman_update_command "pacsync --updated"

#define install_proprietary_command(target) yon_char_append("pacinstall --install --yolo ",target)

#define delete_proprietary_command(target) yon_char_append("pacinstall --remove --yolo ",target)

#define get_info_proprietary_command(target) yon_char_append("pamac-manager --details=",target)

#define yon_check_database_command "pacman -Sqs >/dev/null"

#define pacman_unlock_database_command "rm -f /var/lib/pacman/db.lck"

#define yon_get_kernels_installed "find /usr/lib/modules/ -maxdepth 2 -type f -iname \"pkgbase\" -exec cat {} + 2>/dev/null"

#define icon_devices_path "com.ublinux.libublsettingsui-gtk3.database-symbolic"
#define icon_module_path "com.ublinux.libublsettingsui-gtk3.dropbox-symbolic"
#define icon_package_path "com.ublinux.libublsettingsui-gtk3.lookup-symbolic"

#define yon_get_is_installed_command(target) yon_char_append("pacman -Q ",target)
#define yon_get_is_exist_command(target) yon_char_append("pacman -Ss ",target)
#define yon_get_all_pacman_packages_command "pacman -Slq"
#define yon_get_add_installed_packages "pacman -Qq"

#define get_adapter_info_json "lshw -c display -quiet -json"
#define get_drivers_for_card_command "lspci | grep -E ' VGA | Display ' | cut -d' ' -f 1 | xargs -i lspci -k -s {}|grep Kernel|sed -e 's/^\t*//g' -e 's/Kernel driver in use: /uses=/g' -e 's/Kernel modules: /all=/g'"

#define XORG_MONITOR(port) yon_char_append("XORG_MONITOR[",yon_char_append(port,"]"))
#define VGADRV_AUTO "VGADRV_AUTO"
#define VGADRV_NOFREE "VGADRV_NOFREE"
#define XORG_EXT "XORG_EXT"
#define XORG_DPI "XORG_DPI"
#define FAILSAFEATI "FAILSAFEATI"
#define FAILSAFENVIDIA "FAILSAFENVIDIA"
#define OPTIRUN "OPTIRUN"
#define PRIMUSRUN "PRIMUSRUN"
#define INTEGRATEDVGA "INTEGRATEDVGA"

#define GAPFIX1_parameter "ENVIRONMENT[profile:__GL_YIELD]"
#define GAPFIX1_command "ubconfig --source global get [system] ENVIRONMENT[profile:__GL_YIELD]"
#define GAPFIX2_parameter "ENVIRONMENT[profile:KWIN_TRIPLE_BUFFER]"
#define GAPFIX2_command "ubconfig --source global get [system] ENVIRONMENT[profile:KWIN_TRIPLE_BUFFER]"

#define VGADRV_AUTO_command "ubconfig --source global get [video] VGADRV_AUTO"
#define VGADRV_NOFREE_command "ubconfig --source global get [video] VGADRV_NOFREE"
#define XORG_EXT_command "ubconfig --source global get [video] XORG_EXT"
#define XORG_DPI_command "ubconfig --source global get [video] XORG_DPI"
#define FAILSAFEATI_command "ubconfig --source global get [video] FAILSAFEATI"
#define FAILSAFENVIDIA_command "ubconfig --source global get [video] FAILSAFENVIDIA"
#define OPTIRUN_command "ubconfig --source global get [video] OPTIRUN"
#define PRIMUSRUN_command "ubconfig --source global get [video] PRIMUSRUN"
#define INTEGRATEDVGA_command "ubconfig --source global get [video] INTEGRATEDVGA"

#define XORG_PARAMETER "XORG_MONITOR"

#define config_get_command(source) yon_char_unite("ubconfig --source ",source," -ea get [video] XORG_MONITOR[*] VGADRV_AUTO VGADRV_NOFREE XORG_EXT XORG_DPI FAILSAFEATI FAILSAFENVIDIA OPTIRUN PRIMUSRUN INTEGRATEDVGA -- [system] ENVIRONMENT[profile:__GL_YIELD] ENVIRONMENT[profile:KWIN_TRIPLE_BUFFER]",NULL)
#define config_get_default_command ""

#define config_get_global_only_parameters ""
#define config_get_local_only_parameters ""

#define XORG_MONITOR_get_command "ubconfig --source global get [video] XORG_MONITOR[*]"

typedef struct{
    char* command;
    void *data;
} thread_input;

typedef char* string;

__attribute__((unused)) static \
string version_application;

#define _(String) gettext(String)

typedef dictionary* monitor_config;
typedef dictionary* proprietary_config;
typedef dictionary* monitor_view;

typedef struct {
    config_str line;
    int size;
} resolution_supported;

typedef struct
{
    template_window_fields
    GtkWidget *MainBox;
    GtkWidget *MainOverlay;
    GtkWidget *MainSpinner;

    GtkWidget *GSWarningLabel;

    GtkWidget *AutoDriverCombo;
    GtkWidget *FreeDriverCombo;
    GtkWidget *FailsafeNvidiaCombo;
    GtkWidget *FailsafeAMDCombo;
    GtkWidget *MonitorsBox;
    GtkWidget *DontSwitchDisplaysOffCombo;
    GtkWidget *DisplayScalingCombo;
    GtkWidget *DisplayDiscreteOnly;
    GtkWidget *OptirunCombo;
    GtkWidget *OptirunEntry;
    GtkWidget *OptirunButton;
    GtkWidget *PrimusrunCombo;
    GtkWidget *PrimusrunEntry;
    GtkWidget *PrimusrunButton;
    GtkWidget *FrameGapCombo;

    GtkWidget *KernelsCombo;
    GtkWidget *InfoButton;

    GtkWidget *DriverModulesTab;
    GtkWidget *DriversTab;
    // GtkWidget *MainTabLabel;
    // GtkWidget *DriversTabLabel;
    // GtkWidget *InformationTabLabel;
    GtkWidget *InformationFrameLabel;
    GtkWidget *InformationOverlay;
    GtkWidget *InformationCompanyLogoImage;
    GtkWidget *InformationOverlay2;
    GtkWidget *InformationCompanyLogoImage2;
    GtkWidget *InformationLabel;
    GtkWidget *InformationLabel2;

    GtkWidget *TerminalOverlay;
    GtkWidget *TerminalBox;
    GtkWidget *TerminalInfoLabel;
    GtkWidget *TerminalMoreButton;
    GtkWidget *TerminalCancelButton;
    GtkWidget *TerminalScroll;
    GtkWidget *TerminalMoreRevieler;
    GtkWidget *DriversLoadingOverlay;
    GtkWidget *DriversLoadingSpinner;

    GtkWidget *DriversList;
    GtkWidget *InstalledBox;
    GtkWidget *InstalledModuleLabel;
    GtkWidget *InstalledPackageLabel;
    GtkWidget *KernelLabel;
    GtkWidget *DriverLabel;
    GtkWidget *DescriptionLabel;
    GtkWidget *DevicesLabel;
    GtkWidget *UnlockPacmanButton;

    GtkWidget *MoreButton;
    GtkWidget *CancelButton;
    GtkWidget *TerminalPaned;
    GtkWidget *TerminalRevealer;
    GtkWidget *InstallTerminal;
    GtkWidget *TerminalMoveBox;
    GtkWidget *TerminalMoveTargetBox;

    GtkWidget *MenusTab;

    GtkWidget *LoadDriversButton;
    GtkWidget *SupportedDevicesButton;
    GtkWidget *AboutModuleButton;
    GtkWidget *AboutPackageButton;

    rmb_menu_window *menu;
} main_window;

typedef struct
{
    template_config_fields

    config_str loaded_config;
    int configsize;
    int autoChooseDrivers;
    monitor_view monitor_visuals;
    monitor_config monitors;
    proprietary_config proprietary;
    GHashTable *ports_table;
    char *failsafenVidia;
    char *failsafeATI;
    int descreteOnly;
    char *optirun;
    char *primusrun;
    int gapfix;
    GHashTable *resolutions;
    int resolutions_size;
    config_str resolutions_sorted;
    render_data status_render;

    dictionary *monitor_output_layers;
    GtkWidget *pack_box;
    int dblock;
    int save_config;
    main_window *widgets;

    GMutex progress_mutex;
    int progress_active;

} config;

extern config main_config;

typedef struct {
    GtkWidget *MainBox;
    GtkWidget *ModuleInstalledCheck;
    GtkWidget *PackageInstalledCheck;
    GtkWidget *KernelLabel;
    GtkWidget *DriverLabel;
    GtkWidget *DescriptionLabel;
    GtkWidget *DevicesBox;
    GtkWidget *DevicesInfoButton;
    GtkWidget *DevicesLabel;

    char *name;
    char *module;
    char *package;
    char *kernel;
    char *devices;
    char *description;
    int module_installed;
    int package_installed;
    int module_exist;
    int package_exist;
    int supported_devices_avaliable;
} driver_struct;

typedef struct
{
    int main;
    int enable;
    int position;
    char *position_port;
    char *port;
    char *resolution;
    config_str resolutionCapabilities;
    int frequency;
    int rotation;
    char *stringparameters;
    int dpms;
    int resolution_size;
    int cvt;
    int reduced;
    int gtf;
    int show_usupported;
} monitorconfig;

typedef struct {
    GtkWidget *combo;
    GtkWidget *tree;
} combo_tree;

typedef struct
{
    char *curport;
    config_str resolutions;
    int resolutionssize;

    GtkWidget *MainWindow;
    GtkWidget *StatusBox;
    GtkWidget *HeadLabel;
    GtkWidget *EnableConfigurationBox;
    GtkWidget *InterfaceConfigurationBox;
    GtkWidget *EnableCheck;
    GtkWidget *PortCombo;
    GtkWidget *ManualCheck;
    GtkWidget *PortEntry;
    GtkWidget *MainCheck;
    GtkWidget *ResolutionCombo;
    GtkWidget *ResolutionEntry;
    GtkWidget *UnsupportedCheck;
    GtkWidget *FrequencyCombo;
    GtkWidget *RotationCombo;
    GtkWidget *PositionPosCombo;
    GtkWidget *PositionPortCombo;
    GtkWidget *DoNotSwitchOffCheck;
    GtkWidget *ModelineCVTCheck;
    GtkWidget *UseCVTReducedCheck;
    GtkWidget *ModelineGTFCheck;
    GtkWidget *ParameterLineCheck;
    GtkWidget *ParameterLineEntry;
    GtkWidget *CancelButton;
    GtkWidget *SaveButton;
} monitor_edit_window;

typedef struct {
    GtkWidget *MainFlow;
    // GtkWidget *ScreenOverlay;
    // GtkWidget *MonitorImage;
    GtkWidget *MonitorInfoBox;
    GtkWidget *NameLabel;
    GtkWidget *ResoulutionLabel;
    GtkWidget *DeleteButton;
    GtkWidget *SwitchButton;
    GtkWidget *ConfigureButton;
    GtkWidget *AddButton;
    char *target_port;
    char *target_resolution;
} monitor_data;

typedef struct
{
    GtkWidget *window;

    GtkWidget *propriearyTreeView;
    GtkTreeViewColumn *ProprietaryDriverColumn;
    GtkTreeViewColumn *ProprietaryDescriptionColumn;
    GtkListStore *list;

    GtkWidget *ProprietaryCloseButton;
    GtkWidget *ProprietaryAcceptButton;
} driver_window;


struct proprietary_struct {
    config_str drivers;
    int drivers_size;
    int module_status;
    int package_status;
    int module_exist;
    int package_exist;
};

struct proprietary_kernel_append_struct {
    main_window *widgets;
    char *kernel;
};

struct adapter_struct {
    main_window *widgets;
    char *adapter_text;
    char *vendor;
};

monitor_data *yon_monitor_new(main_window *widgets,int dull);
void yon_launch_with_output(char *command);
void yon_monitor_view_update();
void on_save_done(main_window *, config_str output, int size);
void yon_proprietary_get_thread(GtkWidget *self,main_window *widgets);
void on_terminal_done(GtkWidget *terminal,  int size, main_window *widgets);
void on_terminal_more(GtkWidget *self, main_window *widgets);
void on_terminal_destroy(GtkWidget *self, main_window *widgets);
gboolean on_terminal_check_progress(main_window *widgets);
void yon_terminal_start(main_window *widgets, char *usr_command);
void on_driver_pack_selection_change(GtkWidget *, GtkListBoxRow *selection, main_window *widgets);
void on_driver_pack_info(GtkWidget *self, main_window *widgets);
void on_install_activate(GtkWidget *self, main_window *widgets);
void on_module_install_activate(GtkCellRendererToggle* self,gchar* path,main_window *widgets);
gboolean yon_filter_func(GtkTreeModel* model,GtkTreeIter* iter,main_window *widgets);
void on_kernel_filter_changed(GtkWidget *self, main_window *widgets);
void on_port_chosen_changed(GtkWidget *self, monitor_edit_window *window);
void on_resolutions_unsupported_show(GtkToggleButton *self, monitor_edit_window *window);
void yon_interface_save();
void yon_interface_update();
void yon_load_proceed(YON_CONFIG_TYPE type);
void on_config_local_load(GtkWidget *self,main_window *widgets);
void on_config_global_load(GtkWidget *self,main_window *widgets);
void on_config_custom_load(GtkWidget *self,main_window *widgets);
void on_config_global_local_save();
void on_config_local_save();
void on_config_global_save();
void on_config_custom_save(GtkWidget *self, main_window *widgets);
void on_monitor_delete(GtkWidget *self,monitor_data *window);
void on_monitor_switch(GtkWidget *self,monitor_data *window);
void on_monitor_add(GtkWidget *self,main_window *widgets);
void on_monitor_config_save(GtkWidget *self, monitor_edit_window *window);
void yon_monitor_parse(monitor_edit_window *window, char *string);
void on_monitor_configure(GtkWidget *self,monitor_data *window);
void yon_monitor_view_update();
void yon_proprietary_get_thread(GtkWidget *self,main_window *widgets);
// void yon_monitor_view_dictionary_destroy(void *window);
monitor_data *yon_monitor_new(main_window *widgets,int dull);
void yon_monitor_set_resolutions();
void yon_adapter_window_setup(main_window *widgets);
void yon_set_sensitive_from_combo_box(GtkComboBox *toggle, GtkWidget *target);
void on_database_update(void *self,main_window *widgets);
template_main_window *yon_main_window_complete(main_window *widgets);
void config_init();

void yon_proprietary_local_get(main_window *widgets);
gboolean yon_proprietary_append_kernels(struct proprietary_kernel_append_struct *append);
gboolean yon_proprietary_clear(main_window *widgets);
gboolean on_command_execute_success(GtkWidget *,gint status,main_window *widgets);
void on_gapfix_changed(GtkWidget*self, main_window *widgets);

gboolean yon_proprietary_connect(main_window *widgets);
void on_app_chooser_open(GtkWidget *self, main_window *widgets);
gpointer yon_driver_info_launch(void *command);
void on_command_cancel(GtkWidget *,main_window *widgets);
gboolean yon_proprietary_set(main_window *widgets);
void on_devices_info_clicked(GtkWidget *, driver_struct* driver);
driver_struct *yon_driver_struct_new();
void yon_driver_struct_update(main_window *widgets,driver_struct *driver);
void yon_drivers_resize(main_window *);
void on_link_activate(GtkWidget *, char*, driver_struct *driver);
void on_terminal_revealer_open(GtkWidget *, main_window *widgets);
void on_driver_module_info(GtkWidget *, main_window *widgets);
void on_devices_button_clicked(GtkWidget *, main_window *widgets);
int check_rmb_menu(void *data);
void on_install_check(GtkWidget *self,gint status,driver_struct *driver);
void yon_install_buttons_set_sensitive(main_window *widgets,int state);
void on_pacman_db_unlock(void);
char *yon_auto_driver_default(char *target);
char *yon_free_driver_default(char *target);
char *yon_failsafe_driver_default(char *target);
char *yon_ati_driver_default(char *target);
char *yon_switch_display_off_default(char *target);
char *yon_scaling_default(char *target);
char *yon_discrete_default(char *target);
char *yon_optirun_default(char *target);
char *yon_primusrun_default(char *target);
void yon_all_resolutions_update();
void yon_monitor_port_manual(GtkToggleButton *self,monitor_edit_window *monitors);
int yon_string_compare(char **a, char **b);
char *yon_char_extend(char *target, char symbol, size_t length);
void on_driver_child_ready(VteTerminal *terminal, GPid pid, GError *, gpointer );
void on_paned_position_changed(GtkWidget *, GdkEvent*,main_window *widgets);
gboolean on_db_update_done(GtkWidget *,gint ,main_window *widgets);
void yon_adapter_update(struct adapter_struct *adapter);
void *yon_load_adapter(main_window *widgets);

#endif