/*
This file is part of Gnome Photo Printer.

    Gnome Photo Printer 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.

    Gnome Photo Printer 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 Gnome Photo Printer; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include <stdio.h>
#include <stdlib.h>
#include <gnome.h>
#include <libgnome/gnome-i18n.h>
#include <glade/glade.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <libgnomevfs/gnome-vfs.h>
#include <libgnomeprint/gnome-print.h>
#include <libgnomeprint/gnome-print-job.h>
#include <libgnomeprintui/gnome-print-dialog.h>
#include <glib/gprintf.h>
#include "gpp_print.h"
#include "gpp_functions.h"
#include "gpp_widget.h"
#include "gpp_callbacks.h"
#include "gpp.h"


gboolean
gpp_check_page_size ()
{
	gboolean ret = TRUE;
	gint x, y;

	if (gpp_calculate_pics_on_page ()!=0)
		return TRUE;

	x = gpp_definition->layout_x;
	y = gpp_definition->layout_y;

	gpp_definition->layout_x = y;
	gpp_definition->layout_y = x;
	if (gpp_calculate_pics_on_page ()==0)
	{
		gtk_widget_show_all (gpp_pagesize);
		ret = FALSE;
	}

	gpp_definition->layout_x = x;
	gpp_definition->layout_y = y;

	return ret;
}


void
gpp_set_layout ()
{
	gfloat width, height;

	switch (gpp_definition->layout)
        {
	case LAYOUT_1:
		gpp_definition->layout_x = gpp_calculate_size_metric_to_dpi (20);
		gpp_definition->layout_y = gpp_calculate_size_metric_to_dpi (25);
		break;

	case LAYOUT_2:
		gpp_definition->layout_x = gpp_calculate_size_metric_to_dpi (15);
		gpp_definition->layout_y = gpp_calculate_size_metric_to_dpi (20);
		break;

	case LAYOUT_3:
		gpp_definition->layout_x = gpp_calculate_size_metric_to_dpi (13);
		gpp_definition->layout_y = gpp_calculate_size_metric_to_dpi (18);
		break;

	case LAYOUT_4:
		gpp_definition->layout_x = gpp_calculate_size_metric_to_dpi (10);
		gpp_definition->layout_y = gpp_calculate_size_metric_to_dpi (15);
		break;

	case LAYOUT_5:
		gpp_definition->layout_x = gpp_calculate_size_metric_to_dpi (9);
		gpp_definition->layout_y = gpp_calculate_size_metric_to_dpi (13);
		break;

	case LAYOUT_6:
		gpp_definition->layout_x = gpp_calculate_size_metric_to_dpi (6);
		gpp_definition->layout_y = gpp_calculate_size_metric_to_dpi (9);
		break;

	case LAYOUT_7:
		gpp_definition->layout_x = gpp_calculate_size_metric_to_dpi (4);
		gpp_definition->layout_y = gpp_calculate_size_metric_to_dpi (5.5);
		break;

	case LAYOUT_8:
		/*
		  Layout for Avery Business Card labels (e.g. 8871)
		*/
		gpp_definition->layout_x = gpp_calculate_size_metric_to_dpi (8.8);
		gpp_definition->layout_y = gpp_calculate_size_metric_to_dpi (5.1);
		break;

	case LAYOUT_CUSTOM:
	    // g_printf("Custom Units Seleciton: %s\n",gtk_combo_box_get_active_text(gpp_custom_units));

		switch (gtk_combo_box_get_active(gpp_custom_units))
			{
			case 0: /* cm */
				/* No conversion necessary */
				width = gtk_spin_button_get_value_as_float (gpp_custom_width);
				height = gtk_spin_button_get_value_as_float (gpp_custom_height);
				break;

			case 1: /* in */
				/* Convert from inches to cm */
				width = (gtk_spin_button_get_value_as_float (gpp_custom_width))*2.54;
				// g_printf("Converted Width: %f\n",width);

				height = (gtk_spin_button_get_value_as_float (gpp_custom_height))*2.54;
				// g_printf("Converted Height: %f\n",height);
				break;

		}

		gpp_definition->layout_x = gpp_calculate_size_metric_to_dpi (width);
		gpp_definition->layout_y = gpp_calculate_size_metric_to_dpi (height);
		break;
	}
}

/*
	Get the made Settings
	return: true on success
*/
gboolean
gpp_get_settings_from_libgnomeprint ()
{
	gdouble width, height;
	// gboolean to_file;

	if (gnome_print_job_get_page_size (gpp_job, &width, &height) != TRUE)
	{
		g_printf ("Error, couldn't get page size!\n");
		return FALSE;
	}

	gpp_definition->paper_size_x = width;
	gpp_definition->paper_size_y = height;


	/* This truely needs to be fixed!!! Its a bug inside libgnomeprint!!!
	 * if (gnome_print_config_get_boolean
	 * (gpp_config, "PrintToFile", &to_file) != TRUE)
	 * {
	 * g_printf ("Error, couldn't get output definition!\n");
	 * return FALSE;
	 * }
	 * else
	 * {
	 * gpp_definition->to_file = to_file;
	 * }
	 */

	/* Needs to be fixed when libgnomeprintui gets fixed!
	 * if (gnome_print_config_get
	 * (gpp_config, "Settings.Transport.Backend.FileName") == NULL)
	 * {
	 * g_printf ("Error, couldn't get Name of Output File!\n");
	 * return FALSE;
	 * }
	 * else
	 * {
	 * gpp_definition->output_file_name =
	 * g_strdup (gnome_print_config_get
	 * (gpp_config,
	 * "Settings.Transport.Backend.FileName"));
	 * }
	 */

	/* Doing it this way right now! */
	gpp_definition->output_file_name =
		g_strdup (gnome_print_config_get
			  (gpp_config,
			   "Settings.Transport.Backend.FileName"));

	return TRUE;
}

/*
	Show the settings
	return: is TRUE on success
*/
gboolean
gpp_show_settings_from_libgnomeprint ()
{
	GtkTreeIter iter;
	GtkTreeModel *tree;
	gboolean valid;

	g_printf ("Print to file: %d\n", gpp_definition->to_file);
	g_printf ("File Name: %s\n", gpp_definition->output_file_name);
	g_printf ("Width: %f\n", gpp_definition->paper_size_x);
	g_printf ("Height: %f\n", gpp_definition->paper_size_y);
	g_printf ("Layout Type: %d\n", gpp_definition->layout);
	g_printf ("Layout X: %f\n", gpp_definition->layout_x);
	g_printf ("Layout Y: %f\n", gpp_definition->layout_y);
	g_printf ("Rotate: %d\n", gpp_calculate_rotate_pictures ());
	g_printf ("Number of Files: %d\n", gpp_definition->number_of_files);

	tree = GTK_TREE_MODEL (gpp_definition->file_names);

	/* Get the first iter in the list */
	valid = gtk_tree_model_get_iter_first (tree, &iter);


	while (valid)
	{
		/* Walk through the list, reading each row */
		gchar *file_name;

		gtk_tree_model_get (tree, &iter, FILE_COLUMN, &file_name, -1);

		/* Do something with the data */
		g_print ("File Names %s\n", file_name);
		g_free (file_name);

		valid = gtk_tree_model_iter_next (tree, &iter);
	}

	return TRUE;
}

/*
	Calculate the pictures sizes (in metric)
	size: is in cm
	return: is in dots
*/
gdouble
gpp_calculate_size_metric_to_dpi (gdouble size)
{
	gdouble value;
	value = (size / 2.54) * PRINTER_DPI;
	return value;
}

/*
	Put as many pictures on one page as possibly!
	With or without rotating the pictures?
	Also updates the gpp_definition->layout information.
	return: true or false
*/

gboolean
gpp_calculate_rotate_pictures ()
{
	gdouble help, ax, ay, bx, by;
	gint cx, cy, dx, dy;

	ax = gpp_definition->paper_size_x;
	ay = gpp_definition->paper_size_y;

	bx = gpp_definition->layout_x;
	by = gpp_definition->layout_y;

	cx = gpp_calculate_fit_to_page (ax, bx);
	cy = gpp_calculate_fit_to_page (ay, by);

	dx = gpp_calculate_fit_to_page (ax, by);
	dy = gpp_calculate_fit_to_page (ay, bx);

	if ((cx * cy) <= (dx * dy))
	{
		help = gpp_definition->layout_x;
		gpp_definition->layout_x = gpp_definition->layout_y;
		gpp_definition->layout_y = help;
		return TRUE;
	}

	return FALSE;
}

gint
gpp_calculate_fit_to_page (gdouble page, gdouble pic)
{
	return page / pic;
}

/*
	Returns the number of pages
	return: number of pages
*/
gint
gpp_calculate_number_of_sites ()
{
	gint sites;

	sites = gpp_definition->number_of_files /
		gpp_calculate_pics_on_page ();
	if ((gpp_definition->number_of_files %
	     gpp_calculate_pics_on_page ()) > 0)
		sites++;

	return sites;
}

/*
	Calculates the number of pictures that fit on one page.
	return: number of pictures
*/
gint
gpp_calculate_pics_on_page ()
{
	gdouble ax, ay, bx, by;
	gint cx, cy;

	ax = gpp_definition->paper_size_x;
	ay = gpp_definition->paper_size_y;

	bx = gpp_definition->layout_x;
	by = gpp_definition->layout_y;

	cx = gpp_calculate_fit_to_page (ax, bx);
	cy = gpp_calculate_fit_to_page (ay, by);

	return cx * cy;

}

/*
	Calculates the space between each picture
	return: space between pictures
*/
gdouble
gpp_calculate_space_between_pics (gdouble page, gdouble pic)
{
	gdouble spaces;

	spaces = (page -
		  (gpp_calculate_fit_to_page (page, pic) * pic)) /
		(gpp_calculate_fit_to_page (page, pic) + 1);

	return spaces;
}

/*
	Rotates one picture at 90 degree
	input: pixbuf
	return: pixbuf
*/
GdkPixbuf *
gpp_gdk_rotate_pixbuf_90 (GdkPixbuf * pixbuf)
{
	GdkPixbuf *pixbuf_new;
	GdkColorspace colorspace;
	guchar *raw_image;
	gboolean has_alpha;
	gint x, y, rowstride, height, width, bits_per_sample;

	raw_image = gdk_pixbuf_get_pixels (pixbuf);
	has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
	rowstride = gdk_pixbuf_get_rowstride (pixbuf);
	height = gdk_pixbuf_get_height (pixbuf);
	width = gdk_pixbuf_get_width (pixbuf);
	bits_per_sample = gdk_pixbuf_get_bits_per_sample (pixbuf);
	colorspace = gdk_pixbuf_get_colorspace (pixbuf);

	pixbuf_new =
		gdk_pixbuf_new (colorspace, has_alpha, bits_per_sample,
				height, width);

	for (x = 0; x < width; x++)
	{
		for (y = 0; y < height; y++)
		{
			gdk_pixbuf_copy_area (pixbuf, x, y, 1, 1, pixbuf_new,
					      height - y - 1, x);
		};
	};

	gdk_pixbuf_unref (pixbuf);

	return pixbuf_new;
}

/*
	Checks if a file_name is an Image
	input: file_name
	output: TRUE or FALSE
*/
gboolean
gpp_check_for_image (gchar * file_name)
{
	GnomeVFSResult result;
	GnomeVFSFileInfo *file_info;

	file_info = gnome_vfs_file_info_new ();
	result = gnome_vfs_get_file_info (file_name, file_info,
					  GNOME_VFS_FILE_INFO_GET_MIME_TYPE);

	if (file_info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_TYPE)
		if (file_info->type == GNOME_VFS_FILE_TYPE_REGULAR)
			if (file_info->
			    valid_fields &
			    GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE)
				if (g_strrstr (file_info->mime_type, "image/")
				    != NULL)
					return TRUE;

	return FALSE;
}
