
#include "gtk-menu.h"

#include "gcore/gcomm.h"
#include "gcore/glaunch.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <unistd.h>
#endif /* WIN32 */
#ifdef darwin
#ifndef PATH_MAX
#include <sys/syslimits.h>  /* only if PATH_MAX missing from limits.h */
#endif
#endif /* darwin */
#include <gtk/gtk.h>
#ifndef WIN32
#define GGTK_PATH_MAX PATH_MAX
#else /* WIN32 */
#include <gdk/gdkwin32.h>
#define GGTK_PATH_MAX MAX_PATH
#define strdup _strdup
#endif /* WIN32 */

static void send_command( GtkWidget *w, char *command)
{
    if (sic_post_command_text( command) == -1) {
        gdk_display_beep( gdk_display_get_default( ));
    }
}

static void _show_uri(char *path)
{
#ifdef WIN32
    char command[GGTK_PATH_MAX];
    sprintf(command, "start %s", path);
    system(command);
#elif GTK_CHECK_VERSION(2,14,0) && !defined(darwin)
    {
        GError *error = NULL;
        GFile *gfile;
        char *uri;

        gfile = g_file_new_for_commandline_arg(path);
        uri = g_file_get_uri(gfile);
        if (!gtk_show_uri(NULL, uri, GDK_CURRENT_TIME, &error) && error != NULL) {
        //if (!g_app_info_launch_default_for_uri(uri, None, &error))
            fprintf(stderr, "%s: Unable to launch %s\n", error->message, uri);
            g_error_free(error);
        }
    }
#else
    if (!fork()) {
        // hide possible errors
        close(2);
#ifdef darwin
        execlp("open", "open", path, NULL);
#endif
        execlp("xdg-open", "xdg-open", path, NULL);
        execlp("htmlview", "htmlview", path, NULL);
        execlp("firefox", "firefox", path, NULL);
        fprintf(stderr, "Error: unable to open \"%s\"\n", path);
        fprintf(stderr, "Neither xdg-open, nor htmlview, nor firefox is available\n");
        exit(1);
    }
#endif
}

static void open_uri( GtkWidget *w, char *uri)
{
    _show_uri(uri);
}

static GtkWidget *s_menu_window = NULL;

/* This callback quits the program */
static void gtk_destroy_event( GtkWidget *widget, gpointer data)
{
    //printf("gtk-menu: Enter gtk_destroy_event\n");
    s_menu_window = NULL;
#if 0
    gtk_main_quit( );
#endif
    //printf("gtk-menu: Leave gtk_destroy_event\n");
}

int run_gtk_menu_args( int argc, char **argv)
{
    GtkWidget *window;
    GtkWidget *menu_bar;
    GtkWidget *menu_pane;
    GtkWidget *item;
    GtkWidget *menu_stack[10];
    int menu_stack_index = -1;
    int i;
    int comm_id;
    char filename[GGTK_PATH_MAX];
    FILE *fd;
    char windowtitle[TITLELENGTH];
    char helpfilename[HLPFILELNGTH];
    char line[512];

    i = 1;
    comm_id = atoi( argv[i++]);
    strcpy( filename, argv[i++]);

    fd = fopen( filename, "r");

    fgets( windowtitle, TITLELENGTH, fd);
    windowtitle[strlen( windowtitle) - 1] = '\0'; // suppress line feed

    fgets( helpfilename, HLPFILELNGTH, fd);
    helpfilename[strlen( helpfilename) - 1] = '\0'; // suppress line feed

#if 0
    gdk_threads_enter( );
    gtk_init( &argc, &argv);
#endif

    if (s_menu_window != NULL) {
        /* Destroy last menu */
        gtk_widget_destroy( s_menu_window);
    }

    /* Create a new window */
    window = gtk_window_new( GTK_WINDOW_TOPLEVEL);
    gtk_window_set_focus_on_map( GTK_WINDOW(window), FALSE);
#if 0 && !defined(darwin)
    /* menu don't work on mac with this setting */
    gtk_window_set_accept_focus( GTK_WINDOW(window), FALSE);
#endif
    s_menu_window = window;

    /* Set the window title */
    gtk_window_set_title( GTK_WINDOW(window), windowtitle);

    /* Set a handler for delete_event that immediately
     * exits GTK. */
    g_signal_connect( G_OBJECT(window), "destroy",
                      G_CALLBACK(gtk_destroy_event), NULL);

    /* Sets the border width of the window. */
    gtk_container_set_border_width( GTK_CONTAINER(window), 1);

    menu_bar = gtk_menu_bar_new( );

    while (fgets( line, sizeof( line), fd) != NULL) {
        line[strlen( line) - 1] = '\0'; // suppress line feed
        if (strncmp( line, "MENU", 4) == 0) {
            fgets( line, sizeof( line), fd);
            line[strlen( line) - 1] = '\0'; // suppress line feed

            menu_pane = gtk_menu_new( );
            menu_stack[++menu_stack_index] = menu_pane;
            item = gtk_menu_item_new_with_label( line);
            gtk_menu_item_set_submenu( GTK_MENU_ITEM(item), menu_pane);
            if (menu_stack_index <= 0) {
                gtk_menu_bar_append( GTK_MENU_BAR(menu_bar), item);
            } else {
                gtk_menu_shell_append( GTK_MENU_SHELL(menu_stack[menu_stack_index - 1]), item);
            }

        } else if (strncmp( line, "ENDMENU", 7) == 0) {
            menu_stack_index--;
        } else {
            int uri;
            if (strncmp( line, "<URI>", 5) == 0) {
                uri = 1;
                fgets( line, sizeof( line), fd);
                line[strlen( line) - 1] = '\0'; // suppress line feed
            } else {
                uri = 0;
            }

            item = gtk_menu_item_new_with_label( line);
            if (menu_stack_index < 0) {
                gtk_menu_bar_append( GTK_MENU_BAR(menu_bar), item);
            } else {
                gtk_menu_shell_append( GTK_MENU_SHELL(menu_stack[menu_stack_index]), item);
            }

            fgets( line, sizeof( line), fd);
            line[strlen( line) - 1] = '\0'; // suppress line feed

            g_signal_connect( G_OBJECT(item), "activate",
                G_CALLBACK(uri ? open_uri : send_command),
                (gpointer)strdup( line));
        }
    }

    fclose( fd);

    unlink( filename);

    gtk_container_add( GTK_CONTAINER(window), menu_bar);

    gtk_widget_show_all( window);

#if 0
    gtk_main( );
    gdk_threads_leave( );
#endif

    return 0;
}

static int _on_run_menu( void *i)
{
    run_gtk_menu_args((int)(size_t)i, sic_get_static_argv( ));
    // do not call again
    return FALSE;
}

void run_gtk_menu( const char *file)
{
    int i;
    char **argv;

    launch_gtv_main_loop( NULL);

    argv = sic_get_static_argv( );
    i = 0;
    strcpy( argv[i++], "undefined");
    strcpy( argv[i++], "0");
    strcpy( argv[i++], file);
    argv[i] = NULL;

    //run_gtk_menu_args( i, argv);
    g_idle_add(_on_run_menu, (gpointer)(size_t)i);
}

void kill_gtk_menu()
{
    //printf("gtk-menu: Enter kill_gtk_menu\n");
    if (s_menu_window != NULL)
        /* Destroy last menu */
        gtk_widget_destroy( s_menu_window);
    //printf("gtk-menu: Leave kill_gtk_menu\n");
}

