/* 
 * Copyright (C) 2007 Carlos Garcia Campos  <carlosgc@gnome.org>
 *
 * 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, 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 <gtk/gtk.h>
#include <poppler.h>
#include <string.h>

#include "info.h"
#include "fonts.h"
#include "render.h"
#include "page.h"
#include "outline.h"
#include "links.h"
#include "forms.h"
#include "transitions.h"
#include "images.h"
#include "annots.h"
#include "attachments.h"
#include "layers.h"
#include "text.h"
#include "find.h"

enum {
	PGD_TITLE_COLUMN,
	PGD_NPAGE_COLUMN,
	PGD_WIDGET_COLUMN,
	N_COLUMNS
};

typedef struct {
	const gchar *name;
	GtkWidget   *(* create_widget) (PopplerDocument *document);
} PopplerGlibDemo;

static const PopplerGlibDemo demo_list[] = {
	{ "Info",             pgd_info_create_widget },
	{ "Fonts",            pgd_fonts_create_widget },
	{ "Render",           pgd_render_create_widget },
	{ "Page Info",        pgd_page_create_widget },
	{ "Outline",          pgd_outline_create_widget },
	{ "Links",            pgd_links_create_widget },
	{ "Forms",            pgd_forms_create_widget },
	{ "Page Transitions", pgd_transitions_create_widget },
	{ "Images",           pgd_images_create_widget },
	{ "Annots",           pgd_annots_create_widget },
	{ "Attachments",      pgd_attachments_create_widget },
	{ "Layers",           pgd_layers_create_widget },
	{ "Text",             pgd_text_create_widget },
	{ "Find",             pgd_find_create_widget }
};

static void
pgd_demo_changed (GtkTreeSelection *selection,
		  GtkNotebook      *notebook)
{
	GtkTreeModel *model;
	GtkTreeIter   iter;

	if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
		gint n_page;
		
		gtk_tree_model_get (model, &iter,
				    PGD_NPAGE_COLUMN, &n_page,
				    -1);
		gtk_notebook_set_current_page (notebook, n_page);
	}
}

static GtkWidget *
pgd_demo_list_create (void)
{
	GtkWidget       *treeview;
	GtkListStore    *model;
	GtkCellRenderer *renderer;
	gint             i;

	model = gtk_list_store_new (N_COLUMNS,
				    G_TYPE_STRING,
				    G_TYPE_INT,
				    G_TYPE_POINTER);
	treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));

	renderer = gtk_cell_renderer_text_new ();
	gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview),
						     0, "Demos",
						     renderer,
						     "text", PGD_TITLE_COLUMN,
						     NULL);
	
	for (i = 0; i < G_N_ELEMENTS (demo_list); i++) {
		GtkTreeIter iter;

		gtk_list_store_append (model, &iter);
		gtk_list_store_set (model, &iter,
				    PGD_TITLE_COLUMN, demo_list[i].name,
				    PGD_NPAGE_COLUMN, i,
				    -1);
	}

	g_object_unref (model);
	
	return treeview;
}

static GtkWidget *
pdg_demo_notebook_create (PopplerDocument *document)
{
	GtkWidget *notebook;
	gint       i;

	notebook = gtk_notebook_new ();
	gtk_notebook_set_show_tabs (GTK_NOTEBOOK (notebook), FALSE);
	gtk_notebook_set_show_border (GTK_NOTEBOOK (notebook), FALSE);
	
	for (i = 0; i < G_N_ELEMENTS (demo_list); i++) {
		GtkWidget *demo_widget;

		demo_widget = demo_list[i].create_widget (document);
		gtk_notebook_append_page (GTK_NOTEBOOK (notebook), demo_widget, NULL);
		gtk_widget_show (demo_widget);
	}

	return notebook;
}

gint main (gint argc, gchar **argv)
{
	PopplerDocument  *document;
	GtkWidget        *win;
	GtkWidget        *hbox;
	GtkWidget        *notebook;
	GtkWidget        *treeview;
	GtkTreeSelection *selection;
	gchar            *uri;
	GTimer           *timer;
	GError           *error = NULL;

	if (argc != 2) {
		g_print ("Usage: poppler-glib-demo FILE\n");
		return 1;
	}

	if (!g_thread_supported ())
		g_thread_init (NULL);

	gtk_init (&argc, &argv);

#if GLIB_CHECK_VERSION (2,15,0)
	GFile *file;

	file = g_file_new_for_commandline_arg (argv[1]);
	uri = g_file_get_uri (file);
	g_object_unref (file);
#else
	if (g_path_is_absolute (argv[1])) {
		uri = g_filename_to_uri (argv[1], NULL, &error);
	} else if (g_ascii_strncasecmp (argv[1], "file://", strlen ("file://")) == 0) {
		uri = g_strdup (argv[1]);
	} else if (!g_strrstr (argv[1], "://")) {
		gchar *dir;
		gchar *filename;

		dir = g_get_current_dir ();
		filename = g_build_filename (dir, argv[1], NULL);
		g_free (dir);

		uri = g_filename_to_uri (filename, NULL, &error);
		g_free (filename);
	} else {
		g_print ("Error: unsupported uri\n");

		return 1;
	}

	if (error) {
		g_print ("Error: %s\n", error->message);
		g_error_free (error);

		return 1;
	}
#endif /* GLIB_CHECK_VERSION */

	timer = g_timer_new ();
	document = poppler_document_new_from_file (uri, NULL, &error);
	g_timer_stop (timer);
	if (error) {
		g_print ("Error: %s\n", error->message);
		g_error_free (error);
		g_free (uri);

		return 1;
	}

	g_free (uri);

	g_print ("Document successfully loaded in %.4f seconds\n",
		 g_timer_elapsed (timer, NULL));
	g_timer_destroy (timer);

	/* Main window */
	win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
	gtk_window_set_default_size (GTK_WINDOW (win), 600, 600);
	gtk_window_set_title (GTK_WINDOW (win), "Poppler GLib Demo");
	g_signal_connect (G_OBJECT (win), "delete-event",
			  G_CALLBACK (gtk_main_quit), NULL);

	hbox = gtk_hbox_new (FALSE, 6);

	treeview = pgd_demo_list_create ();
	gtk_box_pack_start (GTK_BOX (hbox), treeview, FALSE, TRUE, 0);
	gtk_widget_show (treeview);
	
	notebook = pdg_demo_notebook_create (document);
	gtk_box_pack_start (GTK_BOX (hbox), notebook, TRUE, TRUE, 0);
	gtk_widget_show (notebook);

	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
	g_signal_connect (G_OBJECT (selection), "changed",
			  G_CALLBACK (pgd_demo_changed),
			  (gpointer) notebook);

	gtk_container_add (GTK_CONTAINER (win), hbox);
	gtk_widget_show (hbox);
	
	gtk_widget_show (win);

	gtk_main ();

	g_object_unref (document);
	
	return 0;
}
