#include "libublsettings-gtk3.h"

static void child_ready(VteTerminal *terminal, GPid pid, GError *error, gpointer user_data)
{
    if (!terminal) return;
    if (pid == -1) printf("Error\n\n\n");
    else vte_terminal_feed_child(VTE_TERMINAL(terminal),(char*)user_data,strlen((char*)user_data));
}

void yon_terminal_integrated_launch(GtkWidget *place_to_show, char* command, void *endwork_function, void* endwork_function_argument){
    GtkWidget *terminal = vte_terminal_new();
    config_str parsed=NULL;
    int size=0;
    g_shell_parse_argv(command, &size,&parsed, NULL);
    vte_terminal_spawn_async(VTE_TERMINAL(terminal),VTE_PTY_NO_HELPER,NULL,parsed,NULL,G_SPAWN_SEARCH_PATH,NULL,NULL,NULL,2000,NULL,NULL,NULL);
    vte_terminal_set_size(VTE_TERMINAL(terminal),10,15);
    if(endwork_function)
        g_signal_connect(G_OBJECT(terminal), "child-exited", G_CALLBACK(endwork_function), endwork_function_argument);
        vte_terminal_set_scrollback_lines(VTE_TERMINAL(terminal), -1);
        vte_terminal_set_scroll_on_output(VTE_TERMINAL(terminal), TRUE);
        vte_terminal_set_scroll_on_keystroke(VTE_TERMINAL(terminal), TRUE);
        gtk_widget_show_all(terminal);
    }

void yon_terminal_integrated_start(GtkWidget *terminal, char* command){
    gchar *envv[] = { NULL }; 
    config_str parsed=NULL;
    int size=0;
    g_shell_parse_argv(command, &size,&parsed, NULL);
    vte_terminal_spawn_async(VTE_TERMINAL(terminal),VTE_PTY_NO_HELPER,"/bin",parsed,envv,G_SPAWN_SEARCH_PATH,NULL,NULL,NULL,20,NULL,NULL,NULL);
    vte_terminal_set_size(VTE_TERMINAL(terminal),10,15);
        vte_terminal_set_scrollback_lines(VTE_TERMINAL(terminal), -1);
        vte_terminal_set_scroll_on_output(VTE_TERMINAL(terminal), TRUE);
        vte_terminal_set_scroll_on_keystroke(VTE_TERMINAL(terminal), TRUE);
        gtk_widget_show_all(terminal);
    }

void yon_terminal_integrated_start_shell(GtkWidget *terminal, char* command, void *endwork_function, void* endwork_function_argument){
    char **commands=new_arr(char*,2);
    gchar **envp = g_get_environ();
    commands[0]=(gchar *)g_strdup(g_environ_getenv(envp, "SHELL"));
    commands[1]=NULL;
    char **env=new_arr(char*,2);
    env[0]="";
    env[1]=NULL;
    vte_terminal_set_size(VTE_TERMINAL(terminal),10,15);
    VtePty *pty = vte_pty_new_sync(VTE_PTY_DEFAULT,NULL,NULL);
    vte_terminal_set_pty(VTE_TERMINAL(terminal),pty);
    char *install_command=yon_char_unite("PS1=\"\";tput reset; tput cup 0 0; tput ed; ",command,command[strlen(command)-1]=='\n'?"":";"," STATUS=$?; stty -echo; exit ${STATUS}","\n",NULL); 
    if(endwork_function)
        g_signal_connect(G_OBJECT(terminal), "child-exited", G_CALLBACK(endwork_function), endwork_function_argument);
    printf("%s\n",install_command);
     vte_terminal_spawn_async(VTE_TERMINAL(terminal),
        VTE_PTY_DEFAULT,
        NULL,   
        commands,   
        NULL,  
        0,      
        NULL, NULL,
        NULL,   
        -1, 
        NULL, 
        child_ready,    
        install_command); 
    vte_pty_spawn_async(pty,
        NULL,        
        commands,      
        NULL,         
        0,            
        NULL, NULL,   
        NULL,         
        -1,           
        NULL,         
        NULL,           
        NULL);        
        vte_terminal_set_scrollback_lines(VTE_TERMINAL(terminal), -1);
        vte_terminal_set_scroll_on_output(VTE_TERMINAL(terminal), TRUE);
        vte_terminal_set_scroll_on_keystroke(VTE_TERMINAL(terminal), TRUE);
        gtk_widget_show_all(terminal);
    }

    void __on_yon_terminal_done(GtkWidget *, int state, terminal_window_struct *data){
        if (!state) yon_ubl_status_box_spawn(GTK_CONTAINER(data->StatusBox),data->success_label,0,BACKGROUND_IMAGE_SUCCESS_TYPE);
        else yon_ubl_status_box_spawn(GTK_CONTAINER(data->StatusBox),data->fail_label,0,BACKGROUND_IMAGE_FAIL_TYPE);
    }

    struct terminal_window {
        GtkWidget *window;
        GtkWidget *header;
        GtkWidget *terminal;
        GtkWidget *status_box;
        GtkWidget *scroll;
        GtkWidget *button;

        char *command;
    };

    terminal_window_struct *yon_terminal_window_launch(GtkWindow *parent_window, char *command, char *success_label,char *fail_label){

        terminal_window_struct *data = malloc(sizeof(terminal_window_struct));
        data->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        data->header = gtk_header_bar_new();
        data->terminal = vte_terminal_new();
        data->StatusBox = gtk_box_new(GTK_ORIENTATION_VERTICAL,5);
        data->box = gtk_box_new(GTK_ORIENTATION_VERTICAL,5);
        data->terminal_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,5);
        data->scroll = gtk_scrollbar_new(GTK_ORIENTATION_VERTICAL,gtk_scrollable_get_vadjustment(GTK_SCROLLABLE(data->terminal)));
        gtk_widget_set_size_request(data->window,450,300);

        gtk_window_set_titlebar(GTK_WINDOW(data->window),data->header);
        gtk_container_add(GTK_CONTAINER(data->window),data->box);
        gtk_box_pack_start(GTK_BOX(data->box),data->StatusBox,0,0,0);
        gtk_box_pack_start(GTK_BOX(data->box),data->terminal_box,1,1,0);
        gtk_box_pack_start(GTK_BOX(data->terminal_box),data->terminal,1,1,0);
        gtk_box_pack_start(GTK_BOX(data->terminal_box),data->scroll,0,0,0);
        gtk_widget_set_margin_bottom(data->terminal_box,5);
        gtk_widget_set_margin_start(data->terminal_box,5);
        gtk_widget_set_margin_end(data->terminal_box,5);
        gtk_widget_show_all(data->window);

        vte_terminal_set_scrollback_lines(VTE_TERMINAL(data->terminal),-1);
        
        gtk_window_set_modal(GTK_WINDOW(data->window),1);
        gtk_header_bar_set_show_close_button(GTK_HEADER_BAR(data->header),1);
        gtk_window_set_title(GTK_WINDOW(data->window),gtk_window_get_title(parent_window));
        gtk_window_set_icon_name(GTK_WINDOW(data->window),gtk_window_get_icon_name(parent_window));

        data->success_label=success_label;
        data->fail_label=fail_label;
            g_signal_connect(G_OBJECT(data->terminal), "child-exited", G_CALLBACK(__on_yon_terminal_done), data);
        yon_terminal_integrated_start(data->terminal,command);
        return data;
    }

    void yon_terminal_window_launch_shell(GtkWindow *parent_window, char *command, char *success_label,char *fail_label){

        terminal_window_struct *data = malloc(sizeof(terminal_window_struct));
        GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        GtkWidget *header = gtk_header_bar_new();
        GtkWidget *terminal = vte_terminal_new();
        GtkWidget *status_box = gtk_box_new(GTK_ORIENTATION_VERTICAL,5);
        GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL,5);
        GtkWidget *terminal_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,5);
        GtkWidget *scroll = gtk_scrollbar_new(GTK_ORIENTATION_VERTICAL,gtk_scrollable_get_vadjustment(GTK_SCROLLABLE(terminal)));
        gtk_widget_set_size_request(window,450,300);

        gtk_window_set_titlebar(GTK_WINDOW(window),header);
        gtk_container_add(GTK_CONTAINER(window),box);
        gtk_box_pack_start(GTK_BOX(box),status_box,0,0,0);
        gtk_box_pack_start(GTK_BOX(box),terminal_box,1,1,0);
        gtk_box_pack_start(GTK_BOX(terminal_box),terminal,1,1,0);
        gtk_box_pack_start(GTK_BOX(terminal_box),scroll,0,0,0);
        gtk_widget_set_margin_bottom(terminal_box,5);
        gtk_widget_set_margin_start(terminal_box,5);
        gtk_widget_set_margin_end(terminal_box,5);
        gtk_widget_show_all(window);

        vte_terminal_set_scrollback_lines(VTE_TERMINAL(terminal),-1);
        
        gtk_window_set_modal(GTK_WINDOW(window),1);
        gtk_header_bar_set_show_close_button(GTK_HEADER_BAR(header),1);
        gtk_window_set_title(GTK_WINDOW(window),gtk_window_get_title(parent_window));
        gtk_window_set_icon_name(GTK_WINDOW(window),gtk_window_get_icon_name(parent_window));

        data->StatusBox=status_box;
        data->success_label=success_label;
        data->fail_label=fail_label;
            g_signal_connect(G_OBJECT(terminal), "child-exited", G_CALLBACK(__on_yon_terminal_done), data);
        yon_terminal_integrated_start_shell(terminal,command,NULL,NULL);
    }

    void __on_terminal_window_update_clicked(GtkWidget *,struct terminal_window *window){
        vte_terminal_reset(VTE_TERMINAL(window->terminal),1,1);
        yon_terminal_integrated_start(window->terminal,window->command);
    }

    void yon_terminal_window_update_button_launch(GtkWindow *parent_window, char *command, char *success_label,char *fail_label){
        terminal_window_struct *data = malloc(sizeof(terminal_window_struct));
        struct terminal_window *window = malloc(sizeof(struct terminal_window));
        window->command=command;
        window->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        window->header = gtk_header_bar_new();
        window->terminal = vte_terminal_new();
        window->status_box = gtk_box_new(GTK_ORIENTATION_VERTICAL,5);
        window->button = gtk_button_new_from_icon_name("com.ublinux.libublsettingsui-gtk3.reset-symbolic",GTK_ICON_SIZE_BUTTON);
        GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL,5);
        GtkWidget *box2 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,5);
        GtkWidget *box3 = gtk_box_new(GTK_ORIENTATION_VERTICAL,5);
        GtkWidget *terminal_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,5);
        window->scroll = gtk_scrollbar_new(GTK_ORIENTATION_VERTICAL,gtk_scrollable_get_vadjustment(GTK_SCROLLABLE(window->terminal)));

        gtk_window_set_titlebar(GTK_WINDOW(window->window),window->header);
        gtk_container_add(GTK_CONTAINER(window->window),box);
        gtk_box_pack_start(GTK_BOX(box),window->status_box,0,0,0);
        gtk_box_pack_start(GTK_BOX(box),box2,1,1,0);
        gtk_box_pack_start(GTK_BOX(box2),box3,0,0,0);
        gtk_box_pack_start(GTK_BOX(box2),terminal_box,1,1,0);
        gtk_box_pack_start(GTK_BOX(box3),window->button,0,0,0);
        gtk_box_pack_start(GTK_BOX(terminal_box),window->terminal,1,1,0);
        gtk_box_pack_start(GTK_BOX(terminal_box),window->scroll,0,0,0);

        gtk_style_context_add_class(gtk_widget_get_style_context(window->button),"thin");

        gtk_widget_set_margin_bottom(box2,5);
        gtk_widget_set_margin_start(box2,5);
        gtk_widget_set_margin_end(box2,5);
        gtk_widget_show_all(window->window);

        vte_terminal_set_scrollback_lines(VTE_TERMINAL(window->terminal),-1);
        
        gtk_window_set_modal(GTK_WINDOW(window->window),1);
        gtk_header_bar_set_show_close_button(GTK_HEADER_BAR(window->header),1);
        gtk_window_set_title(GTK_WINDOW(window->window),gtk_window_get_title(parent_window));
        gtk_window_set_icon_name(GTK_WINDOW(window->window),gtk_window_get_icon_name(parent_window));

        data->StatusBox=window->status_box;
        data->success_label=success_label;
        data->fail_label=fail_label;
            g_signal_connect(G_OBJECT(window->terminal), "child-exited", G_CALLBACK(__on_yon_terminal_done), data);
            g_signal_connect(G_OBJECT(window->button), "clicked", G_CALLBACK(__on_terminal_window_update_clicked), window);
        yon_terminal_integrated_start(window->terminal,command);
    }

    void yon_gtk_set_scroll(GtkWidget* self,GdkEventScroll *event, GtkAdjustment *adjustment){
        if (self){};
        gdouble val = gtk_adjustment_get_value(adjustment);
        gdouble lower = gtk_adjustment_get_lower(adjustment);
        gdouble upper = gtk_adjustment_get_upper(adjustment);
        switch (event->direction){
            case GDK_SCROLL_DOWN:
                val+=2;
                if (val>upper) val=upper;
                break;
            case GDK_SCROLL_UP:
                val-=2;
                if (val<lower) val=lower;
                break;
            case GDK_SCROLL_SMOOTH:{
                gdouble y;
                gdk_event_get_scroll_deltas((GdkEvent*)event,NULL,&y);
                val +=y;
                if (val<lower) val=lower;
                if (val>upper) val=upper;
            }
            default:
        }
        gtk_adjustment_set_value(adjustment,val);
    }

    void yon_gtk_widget_set_scroll_window_for_scroll(GtkWidget *target, GtkScrollbar *scroll){
        GtkAdjustment *adjustment = gtk_range_get_adjustment(GTK_RANGE(scroll));
        g_signal_connect(G_OBJECT(target),"scroll-event",G_CALLBACK(yon_gtk_set_scroll),adjustment);
    }