/*
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * See the COPYING file for license information.
 *
 * Guillaume Chazarain <guichaz@gmail.com>
 */

/*******************
 * The Open dialog *
 *******************/

#include "gliv.h"
#include "open_dialog.h"
#include "messages.h"
#include "next_image.h"
#include "files_list.h"
#include "windows.h"
#include "mnemonics.h"
#include "options.h"
#include "loading.h"
#include "glade_image_nr.h"
#include "thumbnails.h"

extern options_struct *options;
extern GlivImage *current_image;

static gchar *saved_path = NULL;

/* From the gtk+-2.4 api documentation */
static void update_preview_cb(GtkFileChooser * file_chooser, gpointer data)
{
    GtkWidget *preview;
    char *filename;
    GdkPixbuf *pixbuf = NULL;

    preview = GTK_WIDGET(data);
    filename = gtk_file_chooser_get_preview_filename(file_chooser);
    if (filename == NULL)
        return;

    start_quiet();

    if (options->force || get_loader(filename) == LOADER_PIXBUF)
        pixbuf = gdk_pixbuf_new_from_file_at_size(filename, 128, 128, NULL);

    stop_quiet();

    g_free(filename);

    gtk_image_set_from_pixbuf(GTK_IMAGE(preview), pixbuf);
    if (pixbuf)
        gdk_pixbuf_unref(pixbuf);

    gtk_file_chooser_set_preview_widget_active(file_chooser, pixbuf != NULL);
}

static gboolean toggle_button(GtkToggleButton * button, gboolean * flag)
{
    *flag = gtk_toggle_button_get_active(button);
    return FALSE;
}

static void add_button(GtkHBox * buttons, const gchar * label, gboolean * flag)
{
    GtkCheckButton *button;

    button =
        GTK_CHECK_BUTTON(gtk_check_button_new_with_mnemonic
                         (add_mnemonic(label)));

    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), *flag);
    g_signal_connect_after(button, "toggled", G_CALLBACK(toggle_button), flag);

    gtk_box_pack_start_defaults(GTK_BOX(buttons), GTK_WIDGET(button));
    gtk_widget_show(GTK_WIDGET(button));
}

/* A GtkFileChooser */
static GtkFileChooser *decorated_dialog(gboolean select_dir)
{
    GtkFileChooserAction action;
    const gchar *label;
    GtkFileChooser *chooser;
    GtkHBox *buttons;

    if (select_dir) {
        action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
        label = _("GLiv: Select a folder to open");
    } else {
        action = GTK_FILE_CHOOSER_ACTION_OPEN;
        label = _("GLiv: Select files to open");
    }

    chooser = GTK_FILE_CHOOSER(gtk_file_chooser_dialog_new(label, NULL,
                                                           action,
                                                           GTK_STOCK_CANCEL,
                                                           GTK_RESPONSE_CANCEL,
                                                           GTK_STOCK_OPEN,
                                                           GTK_RESPONSE_ACCEPT,
                                                           NULL));

    if (saved_path != NULL)
        gtk_file_chooser_set_current_folder(chooser, saved_path);

    if (!select_dir) {
        GtkImage *preview = GTK_IMAGE(gtk_image_new());
        gtk_file_chooser_set_select_multiple(chooser, TRUE);

        gtk_file_chooser_set_preview_widget(chooser, GTK_WIDGET(preview));
        g_signal_connect(chooser, "update-preview",
                         G_CALLBACK(update_preview_cb), preview);
    }

    buttons = GTK_HBOX(gtk_hbox_new(FALSE, 10));
    push_mnemonics();
    add_button(buttons, _("Try to load every file"), &options->force);
    add_button(buttons, _("Recursive directory traversal"),
               &options->recursive);
    pop_mnemonics();

    gtk_file_chooser_set_extra_widget(chooser, GTK_WIDGET(buttons));

    return chooser;
}

static void open_images(gchar ** paths, gint nb)
{
    gint nb_inserted = insert_after_current(paths, nb, FALSE, TRUE);

    new_images(nb_inserted);
}

static void load_selection(GSList * selection)
{
    gint nb = g_slist_length(selection);
    gchar **filenames = g_new(gchar *, nb + 1);
    GSList *list_ptr = selection;
    gchar **tab_ptr = filenames;

    while (list_ptr != NULL) {
        *tab_ptr = list_ptr->data;
        tab_ptr++;
        list_ptr = list_ptr->next;
    }

    *tab_ptr = NULL;

    open_images(filenames, nb);

    g_strfreev(filenames);
}

gboolean menu_open(gboolean select_dir)
{
    GtkFileChooser *dialog;
    gint response;
    GSList *selection = NULL;


    dialog = decorated_dialog(select_dir);
    response = run_modal_dialog(GTK_DIALOG(dialog));

    g_free(saved_path);
    saved_path = gtk_file_chooser_get_current_folder(dialog);

    if (!select_dir && response == GTK_RESPONSE_ACCEPT)
        selection = gtk_file_chooser_get_filenames(dialog);

    gtk_widget_destroy(GTK_WIDGET(dialog));

    if (selection != NULL) {
        /* Opening files */
        load_selection(selection);
        g_slist_free(selection);
    } else if (response == GTK_RESPONSE_ACCEPT)
        /* Opening a dir */
        open_images(&saved_path, 1);

    return FALSE;
}

static GtkWidget *create_pixmap(void *unused1, void *unused2)
{
    return gtk_image_new();
}

static const gchar *selected;
static GtkLabel *dirname_label;
static GtkLabel *filename_label;
static GtkImage *preview;

static gboolean on_image_nr_value_changed(GtkSpinButton * spin)
{
    gchar *dirname;
    gchar *filename;
    GdkPixbuf *thumb;

    int val = gtk_spin_button_get_value_as_int(spin) - 1;
    selected = get_nth_filename(val);

    dirname = g_path_get_dirname(selected);
    filename = g_path_get_basename(selected);

    gtk_label_set_text(dirname_label, dirname);
    gtk_label_set_text(filename_label, filename);

    g_free(dirname);
    g_free(filename);

    thumb = get_thumbnail(selected, NULL);
    gtk_image_set_from_pixbuf(preview, thumb);

    return FALSE;
}

#include "glade_image_nr.c"

gboolean menu_image_nr(void)
{
    GtkDialog *dialog;
    GtkSpinButton *spin;
    gint response;
    gint len = get_list_length();

    if (preview != NULL) {
        /* Currently displayed */
        return FALSE;
    }

    if (len == 0) {
        /* No images */
        return FALSE;
    }

    dialog = GTK_DIALOG(create_image_nr_dialog());

    spin = g_object_get_data(G_OBJECT(dialog), "spinbutton");
    dirname_label = g_object_get_data(G_OBJECT(dialog), "dirname");
    filename_label = g_object_get_data(G_OBJECT(dialog), "filename");
    preview = g_object_get_data(G_OBJECT(dialog), "image");

    gtk_spin_button_set_range(spin, len != 0, len);

    if (current_image != NULL) {
        gint im_nr = get_image_number(current_image);
        gtk_spin_button_set_value(spin, (gdouble) im_nr + 1.0);
    }

    on_image_nr_value_changed(spin);

    response = run_modal_dialog(dialog);
    gtk_widget_destroy(GTK_WIDGET(dialog));
    preview = NULL;

    if (response == GTK_RESPONSE_OK)
        menu_load(selected);

    return FALSE;
}
