/*
 * transmission-remote-gtk - A GTK RPC client to Transmission
 * Copyright (C) 2011-2013  Alan Fitton

 * 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.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "config.h"

#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <json-glib/json-glib.h>
#include <string.h>

#include "hig.h"
#include "requests.h"
#include "trg-client.h"
#include "trg-destination-combo.h"
#include "trg-file-rename-dialog.h"
#include "trg-main-window.h"

struct _TrgFileRenameDialog {
    GtkDialog parent;

    TrgClient *client;
    TrgMainWindow *win;
    TrgFilesTreeView *treeview;
    JsonArray *ids;
    gchar *orig_path;
    GtkWidget *rename_button;
    GtkEntryBuffer *name_entry_buf;
};

typedef struct {
    GtkDialogClass parent_class;
} _TrgFileRenameDialogClass;

G_DEFINE_TYPE(TrgFileRenameDialog, trg_file_rename_dialog, GTK_TYPE_DIALOG)

enum {
    PROP_0,
    PROP_CLIENT,
    PROP_PARENT_WINDOW,
    PROP_TREEVIEW
};

static gchar *trg_file_rename_dialog_get_file_path(GtkTreeModel *model, const GtkTreeIter *iter)
{
    GtkTreeIter current = *iter;
    GtkTreeIter parent;
    gchar *name;
    gchar *filepath;
    gchar *temp_filepath;

    gtk_tree_model_get(model, &current, FILESCOL_NAME, &filepath, -1);

    while (gtk_tree_model_iter_parent(model, &parent, &current)) {
        gtk_tree_model_get(model, &parent, FILESCOL_NAME, &name, -1);
        temp_filepath = g_strdup_printf("%s/%s", name, filepath);
        g_free(name);
        g_free(filepath);
        filepath = temp_filepath;

        current = parent;
    }

    return filepath;
}

static void trg_file_rename_response_cb(GtkDialog *dlg, gint res_id, gpointer data)
{
    TrgFileRenameDialog *self = TRG_FILE_RENAME_DIALOG(dlg);

    if (res_id == GTK_RESPONSE_ACCEPT) {
        const gchar *name = gtk_entry_buffer_get_text(self->name_entry_buf);
        JsonNode *request = torrent_rename_path(self->ids, self->orig_path, name);

        GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(self->treeview));
        trg_files_model_set_accept(TRG_FILES_MODEL(model), FALSE);

        dispatch_rpc_async(self->client, request, on_files_update, self->treeview);
    } else {
        g_free(self->orig_path);
        json_array_unref(self->ids);
    }
    gtk_widget_destroy(GTK_WIDGET(dlg));
}

static void location_changed(GtkComboBox *w, gpointer data)
{
    TrgFileRenameDialog *self = TRG_FILE_RENAME_DIALOG(data);
    gtk_widget_set_sensitive(self->rename_button,
                             gtk_entry_buffer_get_length(self->name_entry_buf));
}

static GObject *trg_file_rename_dialog_constructor(GType type, guint n_construct_properties,
                                                   GObjectConstructParam *construct_params)
{
    GObject *object = G_OBJECT_CLASS(trg_file_rename_dialog_parent_class)
                          ->constructor(type, n_construct_properties, construct_params);
    TrgFileRenameDialog *self = TRG_FILE_RENAME_DIALOG(object);

    gint64 target_id;
    guint count;
    gchar *msg;

    GtkWidget *t;
    guint row = 0;

    /* Get file selection info */

    GtkTreeView *tv = GTK_TREE_VIEW(self->treeview);
    GtkTreeSelection *selection = gtk_tree_view_get_selection(tv);
    GtkTreeModel *model;
    gchar *orig_filename;

    GList *list = gtk_tree_selection_get_selected_rows(selection, &model);
    count = g_list_length(list);

    if (list) {
        GtkTreeIter iter;

        gtk_tree_model_get_iter(model, &iter, (GtkTreePath *)list->data);
        gtk_tree_model_get(model, &iter, FILESCOL_NAME, &orig_filename, -1);

        self->orig_path = trg_file_rename_dialog_get_file_path(model, &iter);
    } else {
        orig_filename = g_strdup("error");
        self->orig_path = NULL;
    }

    /* Populate dialog widget */

    t = hig_workarea_create();

    self->name_entry_buf = gtk_entry_buffer_new(orig_filename, strlen(orig_filename));
    GtkWidget *name_entry = gtk_entry_new_with_buffer(self->name_entry_buf);
    gtk_entry_set_activates_default(GTK_ENTRY(name_entry), TRUE);

    g_signal_connect(name_entry, "changed", G_CALLBACK(location_changed), object);
    hig_workarea_add_row(t, &row, _("Name:"), name_entry, NULL);

    gtk_window_set_destroy_with_parent(GTK_WINDOW(object), TRUE);

    gtk_dialog_add_button(GTK_DIALOG(object), _("_Close"), GTK_RESPONSE_CANCEL);
    self->rename_button
        = gtk_dialog_add_button(GTK_DIALOG(object), _("Rename"), GTK_RESPONSE_ACCEPT);

    gtk_widget_set_sensitive(self->rename_button,
                             gtk_entry_buffer_get_length(self->name_entry_buf));

    gtk_container_set_border_width(GTK_CONTAINER(object), GUI_PAD);

    gtk_dialog_set_default_response(GTK_DIALOG(object), GTK_RESPONSE_ACCEPT);

    gtk_container_set_border_width(GTK_CONTAINER(t), GUI_PAD);

    gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(object))), t, TRUE, TRUE, 0);

    target_id = trg_files_model_get_torrent_id(TRG_FILES_MODEL(model));
    self->ids = json_array_new();
    json_array_add_int_element(self->ids, target_id);

    if (count == 1) {
        msg = g_strdup_printf(_("Rename %s"), orig_filename);
    } else {
        /* this really shouldn't happen since TrgFilesTreeView checks number of
         * selected files before allowing rename */
        msg = g_strdup_printf(_("INTERNAL ERROR: Rename %d files not supported"), count);
        gtk_widget_set_sensitive(self->rename_button, FALSE);
        gtk_widget_set_sensitive(name_entry, FALSE);
    }

    gtk_window_set_transient_for(GTK_WINDOW(object), GTK_WINDOW(self->win));
    gtk_window_set_title(GTK_WINDOW(object), msg);

    g_signal_connect(G_OBJECT(object), "response", G_CALLBACK(trg_file_rename_response_cb),
                     self->win);

    g_free(msg);
    g_free(orig_filename);
    g_list_free_full(list, (GDestroyNotify)gtk_tree_path_free);

    return object;
}

static void trg_file_rename_dialog_get_property(GObject *object, guint property_id, GValue *value,
                                                GParamSpec *pspec)
{
    TrgFileRenameDialog *self = TRG_FILE_RENAME_DIALOG(object);
    switch (property_id) {
    case PROP_CLIENT:
        g_value_set_pointer(value, self->client);
        break;
    case PROP_PARENT_WINDOW:
        g_value_set_object(value, self->win);
        break;
    case PROP_TREEVIEW:
        g_value_set_object(value, self->treeview);
        break;
    default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
        break;
    }
}

static void trg_file_rename_dialog_set_property(GObject *object, guint property_id,
                                                const GValue *value, GParamSpec *pspec)
{
    TrgFileRenameDialog *self = TRG_FILE_RENAME_DIALOG(object);
    switch (property_id) {
    case PROP_CLIENT:
        self->client = g_value_get_pointer(value);
        break;
    case PROP_PARENT_WINDOW:
        self->win = g_value_get_object(value);
        break;
    case PROP_TREEVIEW:
        self->treeview = g_value_get_object(value);
        break;
    default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
        break;
    }
}

static void trg_file_rename_dialog_class_init(TrgFileRenameDialogClass *klass)
{
    GObjectClass *object_class = G_OBJECT_CLASS(klass);

    object_class->get_property = trg_file_rename_dialog_get_property;
    object_class->set_property = trg_file_rename_dialog_set_property;
    object_class->constructor = trg_file_rename_dialog_constructor;

    g_object_class_install_property(
        object_class, PROP_TREEVIEW,
        g_param_spec_object("files-tree-view", "TrgFilesTreeView", "TrgFilesTreeView",
                            TRG_TYPE_FILES_TREE_VIEW,
                            G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME
                                | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));

    g_object_class_install_property(
        object_class, PROP_PARENT_WINDOW,
        g_param_spec_object("parent-window", "Parent window", "Parent window", TRG_TYPE_MAIN_WINDOW,
                            G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME
                                | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));

    g_object_class_install_property(
        object_class, PROP_CLIENT,
        g_param_spec_pointer("trg-client", "TClient", "Client",
                             G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME
                                 | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
}

static void trg_file_rename_dialog_init(TrgFileRenameDialog *self)
{
}

TrgFileRenameDialog *trg_file_rename_dialog_new(TrgMainWindow *win, TrgClient *client,
                                                TrgFilesTreeView *ttv)
{
    return g_object_new(TRG_TYPE_FILE_RENAME_DIALOG, "trg-client", client, "files-tree-view", ttv,
                        "parent-window", win, NULL);
}
