/* eLectrix - a pdf viewer
 * Copyright (C) 2011 Martin Linder <mali2297@users.sf.net>
 *
 * 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, see <http://www.gnu.org/licenses/gpl-2.0.html>.
 */
#include <glib/gstdio.h>
#include "e6x-common.h"
#include "e6x-util.h"
#include "e6x-dialogs.h"
#include "e6x-att-view.h"

#define E6X_ATT_VIEW_GET_PRIVATE(o) \
  (G_TYPE_INSTANCE_GET_PRIVATE ((o), E6X_TYPE_ATT_VIEW, E6xAttViewPrivate))

struct _E6xAttViewPrivate
{
  E6xDocument *doc;
  GList *tmplist;
};

/* Standard GObject methods */
G_DEFINE_TYPE (E6xAttView, e6x_att_view, GTK_TYPE_TREE_VIEW);
static void e6x_att_view_class_init (E6xAttViewClass *klass);
static void e6x_att_view_init (E6xAttView *view);
static void e6x_att_view_finalize (GObject *object);
static void e6x_att_view_dispose (GObject *object);

/* Callback functions to GObject signals */
static void e6x_att_view_row_activated (GtkTreeView *view);
static gboolean e6x_att_view_button_pressed (GtkWidget *view, 
                                             GdkEventButton *event);
static gboolean e6x_att_view_popup_request (GtkWidget *view);
static void e6x_att_view_doc_changed (E6xDocument *doc, 
                                      E6xAttView *view);

/* Helpers */
static void _popup_menu (E6xAttView *view, 
                         GdkEventButton *event);


static void
e6x_att_view_class_init (E6xAttViewClass *klass)
{
  GObjectClass *object_class;

  g_type_class_add_private (klass, sizeof (E6xAttViewPrivate));

  object_class = G_OBJECT_CLASS (klass);
  object_class->dispose = e6x_att_view_dispose;
  object_class->finalize = e6x_att_view_finalize;
}


static void
e6x_att_view_init (E6xAttView *view)
{
  E6xAttViewPrivate *priv = E6X_ATT_VIEW_GET_PRIVATE (view);
  GtkCellRenderer *renderer = NULL;
  GtkTreeViewColumn *column = NULL;
  GtkTreeSelection *selection = NULL;
  
  g_object_set (G_OBJECT (view),
                "enable-search", TRUE,
                "headers-visible", TRUE,
                "reorderable", FALSE,
                "search-column", 0,
                NULL);

  renderer = gtk_cell_renderer_text_new ();
  column = gtk_tree_view_column_new_with_attributes (_("Name"),
                                                     renderer,
                                                     "text", E6X_ATT_COL_NAME,
                                                     NULL);
  gtk_tree_view_column_set_expand (column, TRUE);
  gtk_tree_view_column_set_resizable (column, TRUE);
  gtk_tree_view_column_set_sort_column_id (column, E6X_ATT_COL_NAME);
  gtk_tree_view_column_set_sort_indicator (column, TRUE);
  gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);

  renderer = gtk_cell_renderer_text_new ();
  g_object_set (G_OBJECT (renderer),
                "ellipsize", PANGO_ELLIPSIZE_END,
                "ellipsize-set", TRUE,
                NULL);
  column = gtk_tree_view_column_new_with_attributes (_("Description"),
                                                     renderer,
                                                     "text", E6X_ATT_COL_DESC,
                                                     NULL);
  gtk_tree_view_column_set_expand (column, TRUE);
  gtk_tree_view_column_set_resizable (column, TRUE);
  gtk_tree_view_column_set_sort_column_id (column, E6X_ATT_COL_DESC);
  gtk_tree_view_column_set_sort_indicator (column, TRUE);
  gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);

  renderer = gtk_cell_renderer_text_new ();
  column = gtk_tree_view_column_new_with_attributes (_("Modified"),
                                                     renderer,
                                                     "text", E6X_ATT_COL_MTIME,
                                                     NULL);
  gtk_tree_view_column_set_expand (column, TRUE);
  gtk_tree_view_column_set_resizable (column, TRUE);
  gtk_tree_view_column_set_sort_column_id (column, E6X_ATT_COL_MTIME);
  gtk_tree_view_column_set_sort_indicator (column, TRUE);
  gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);
  
  renderer = gtk_cell_renderer_text_new ();
  column = gtk_tree_view_column_new_with_attributes (_("Size"),
                                                     renderer,
                                                     "text", E6X_ATT_COL_SIZE,
                                                     NULL);
  gtk_tree_view_column_set_resizable (column, FALSE);
  gtk_tree_view_column_set_sort_column_id (column, E6X_ATT_COL_SIZE);
  gtk_tree_view_column_set_sort_indicator (column, TRUE);
  gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);
  
  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
  gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
  
  g_signal_connect (GTK_TREE_VIEW (view), "row-activated",
                    G_CALLBACK (e6x_att_view_row_activated), NULL);
  g_signal_connect (GTK_WIDGET (view), "button-press-event", 
                    G_CALLBACK (e6x_att_view_button_pressed), NULL);
  g_signal_connect (GTK_WIDGET (view), "popup-menu", 
                    G_CALLBACK (e6x_att_view_popup_request), NULL);

  priv->doc = NULL;
  priv->tmplist = NULL;
  view->priv = priv;
}


static void
e6x_att_view_finalize (GObject *object)
{
  G_OBJECT_CLASS (e6x_att_view_parent_class)->finalize (object);
}


static void
_free_file (gpointer data)
{
  gchar *filename = (gchar *) data;
  
  if (filename == NULL)
    return;
  g_unlink (filename);
  g_free (filename);
  filename = NULL;
}


static void
e6x_att_view_dispose (GObject *object)
{
  E6xAttViewPrivate *priv = E6X_ATT_VIEW (object)->priv;
  
  e6x_att_view_set_document (E6X_ATT_VIEW (object), NULL);
  if (priv->tmplist != NULL)
  {
    g_list_free_full (priv->tmplist, &_free_file);
    priv->tmplist = NULL;
  }

  G_OBJECT_CLASS (e6x_att_view_parent_class)->dispose (object);
}


GtkWidget *
e6x_att_view_new (E6xDocument *doc)
{
  E6xAttView *view = NULL;

  view = g_object_new (E6X_TYPE_ATT_VIEW, NULL);
  e6x_att_view_set_document (view, doc);

  return GTK_WIDGET (view);
}


void
e6x_att_view_set_document (E6xAttView *view, E6xDocument *doc)
{
  E6xAttViewPrivate *priv = view->priv;
  
  if (priv->doc != NULL)
  {
    g_signal_handlers_disconnect_by_func (priv->doc,
                                          e6x_att_view_doc_changed,
                                          view);
    gtk_tree_view_set_model (GTK_TREE_VIEW (view), NULL);
    g_object_unref (priv->doc);
  }
  
  priv->doc = doc;
  
  if (priv->doc != NULL)
  {
    g_object_ref (priv->doc);
    gtk_tree_view_set_model (GTK_TREE_VIEW (view), priv->doc->attlist);
    g_signal_connect (priv->doc, "changed::reload",
                      G_CALLBACK (e6x_att_view_doc_changed), 
                      view);
  }
}


gboolean 
e6x_att_view_open_selected (E6xAttView *view)
{
  E6xAttViewPrivate *priv = view->priv;
  GtkTreeSelection *selection = NULL;
	GtkTreeIter iter;
  gchar *name = NULL;
  gchar *tmpl = NULL;
  gint fd = -1;
  gchar *filename = NULL;
  gboolean retval = FALSE;
  
  if (G_UNLIKELY (priv->doc == NULL) || 
      G_UNLIKELY (priv->doc->attlist == NULL))
    return FALSE;
  
  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
  if (gtk_tree_selection_get_selected (selection, &(priv->doc->attlist), &iter))
    gtk_tree_model_get (priv->doc->attlist, &iter, 
                        E6X_ATT_COL_NAME, &name, -1);
  if (name != NULL)
    tmpl = g_strdup_printf ("%s.XXXXXX", name);
  if (tmpl != NULL)
    fd = g_file_open_tmp (tmpl, &filename, NULL);
  if (fd != -1)
  {
    close (fd);
    priv->tmplist = g_list_prepend (priv->tmplist, filename);
    retval = e6x_document_save_att (priv->doc, &iter, filename, NULL); 
    if (retval != FALSE)
      e6x_dialogs_open_with (filename, NULL);
  }
  
  g_free (tmpl);
  g_free (name);  
  
  return retval;
}


gboolean 
e6x_att_view_save_selected (E6xAttView *view)
{
  E6xAttViewPrivate *priv = view->priv;
  GtkTreeSelection *selection = NULL;
	GtkTreeIter iter;
  gchar *name = NULL;
  gchar *path = NULL;
  gboolean retval = FALSE;
  
  if (G_UNLIKELY (priv->doc == NULL) || 
      G_UNLIKELY (priv->doc->attlist == NULL))
    return FALSE;
  
  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
  if (gtk_tree_selection_get_selected (selection, &(priv->doc->attlist), &iter))
    gtk_tree_model_get (priv->doc->attlist, &iter, 
                        E6X_ATT_COL_NAME, &name, -1);
  if (name != NULL)
    path = e6x_dialogs_get_copyname (name, _("Save Attachment"), NULL);
  if (path != NULL)
    retval = e6x_document_save_att (priv->doc, &iter, path, NULL);
  
  g_free (path);
  g_free (name);
  
  return retval;
}


static void 
e6x_att_view_row_activated (GtkTreeView *view)
{
  e6x_att_view_open_selected (E6X_ATT_VIEW (view));
}


static gboolean
e6x_att_view_button_pressed (GtkWidget *view, 
                             GdkEventButton *event)
{
  if (event->type == GDK_BUTTON_PRESS  &&  event->button == 3)
  {
    _popup_menu (E6X_ATT_VIEW (view), event);
    return TRUE;
  }

  return FALSE;
}


static gboolean 
e6x_att_view_popup_request (GtkWidget *view)
{
  _popup_menu (E6X_ATT_VIEW (view), NULL);
  
  return TRUE;
}


static void 
e6x_att_view_doc_changed (E6xDocument *doc, E6xAttView *view)
{
  gtk_tree_view_set_model (GTK_TREE_VIEW (view), doc->attlist);
}


static void
_popup_menu (E6xAttView *view, GdkEventButton *event)
{
  GtkWidget *menu = NULL;
  GtkWidget *menuitem = NULL;

  menu = gtk_menu_new();
  
  menuitem = gtk_menu_item_new_with_mnemonic (_("_Open"));
  gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
  g_signal_connect_swapped (menuitem, "activate",
                            G_CALLBACK (e6x_att_view_open_selected), view);
  
  menuitem = gtk_menu_item_new_with_mnemonic (_("_Save as..."));
  gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
  g_signal_connect_swapped (menuitem, "activate",
                            G_CALLBACK (e6x_att_view_save_selected), view);  
  
  gtk_widget_show_all (menu);

  gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
                  (event != NULL) ? event->button : 0,
                  gdk_event_get_time ((GdkEvent*) event));
}


