###################################################
#
#  Copyright (C) 2008-2013 Mario Kemper <mario.kemper@gmail.com>
#
#  This file is part of Shutter.
#
#  Shutter 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 3 of the License, or
#  (at your option) any later version.
#
#  Shutter 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 Shutter; if not, write to the Free Software
#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
#
###################################################

package Shutter::Pixbuf::Save;

#modules
#--------------------------------------
use utf8;
use strict;
use warnings;

use Gtk3;

#fileparse and tempfile
use File::Basename qw/ fileparse dirname basename /;
use File::Temp qw/ tempfile tempdir /;

#Glib
use Glib qw/TRUE FALSE/;

#--------------------------------------

sub new {
	my $class = shift;

	#constructor
	my $self = {_common => shift, _window => shift};

	#import shutter dialogs
	my $current_window = $self->{_window} || $self->{_common}->get_mainwindow;
	$self->{_dialogs} = Shutter::App::SimpleDialogs->new($current_window);
	$self->{_lp}      = Shutter::Pixbuf::Load->new($self->{_common}, $current_window);

	bless $self, $class;
	return $self;
}

sub save_pixbuf_to_file {
	my $self     = shift;
	my $pixbuf   = shift;
	my $filename = shift;
	my $filetype = shift;
	my $quality  = shift;

	#gettext variable
	my $d = $self->{_common}->get_gettext;

	#check if we need to rotate the image or set the exif data accordingly
	my $option = $self->{_lp}->get_option($pixbuf, 'orientation');
	$option = 1 unless defined $option;

	#FIXME: NOT COVERED BY BINDINGS YET (we use Image::ExifTool instead)
	#we rotate the pixbuf when saving to any other format than jpeg (jpg)
	unless ($filetype eq 'jpeg' || $filetype eq 'jpg') {
		if ($option != 1) {
			$pixbuf = $self->{_lp}->auto_rotate($pixbuf);
		}
	}

	#we have two main ways of saving file
	#when possible we try to use all supported formats of the gdk-pixbuf libs
	#currently this is bmp, jpeg (jpg), png and ico (ico is not useful here)
	my $imagemagick_result = undef;
	if ($filetype eq 'jpeg' || $filetype eq 'jpg') {

		#get quality value from settings if not set
		if (my $settings = $self->{_common}->get_globalsettings_object) {
			if (defined $settings->get_jpg_quality) {
				$quality = $settings->get_jpg_quality;
			} else {
				$quality = 90;
			}
		} else {
			$quality = 90;
		}

		print "Saving file $filename, $filetype, $quality\n" if $self->{_common}->get_debug;

		eval {
			$pixbuf->save($filename, 'jpeg', quality => $quality);

			#FIXME: NOT COVERED BY BINDINGS YET (we use Image::ExifTool instead)
			#~ $pixbuf->set_option( 'orientation' => $option );
			if (my $exif = Shutter::App::Optional::Exif->new()) {

				#new Image::ExifTool instance
				my $exiftool = $exif->get_exiftool;
				if ($exiftool) {

					#Set a new value for a tag
					$exiftool->SetNewValue('Orientation' => $option, Type => 'ValueConv');

					#Write new meta information to a file
					my $success = $exiftool->WriteInfo($filename);
				}
			}
		};
	} elsif ($filetype eq 'png') {

		#get quality value from settings if not set
		if (my $settings = $self->{_common}->get_globalsettings_object) {
			if (defined $settings->get_png_quality) {
				$quality = $settings->get_png_quality;
			} else {
				$quality = 9;
			}
		} else {
			$quality = 9;
		}

		print "Saving file $filename, $filetype, $quality\n" if $self->{_common}->get_debug;

		eval { $pixbuf->save($filename, $filetype, "tEXt::Software" => "Shutter", compression => $quality); };
	} elsif ($filetype eq 'bmp') {
		eval { $pixbuf->save($filename, $filetype); };
	} elsif ($filetype eq 'webp') {

		#get quality value from settings if not set
		if (my $settings = $self->{_common}->get_globalsettings_object) {
			if (defined $settings->get_webp_quality) {
				$quality = $settings->get_webp_quality;
			} else {
				$quality = 98;
			}
		} else {
			$quality = 98;
		}

		print "Saving file $filename, $filetype, $quality\n" if $self->{_common}->get_debug;

		eval { $pixbuf->save($filename, $filetype, "tEXt::Software" => "Shutter", quality => $quality); };
	} elsif ($filetype eq 'pdf') {

		print "Saving file $filename, $filetype\n" if $self->{_common}->get_debug;

		#0.8? => 72 / 90 dpi
		my $surface = Cairo::PdfSurface->create($filename, $pixbuf->get_width * 0.8, $pixbuf->get_height * 0.8);
		my $cr      = Cairo::Context->create($surface);
		$cr->scale(0.8, 0.8);
		Gtk3::Gdk::cairo_set_source_pixbuf($cr, $pixbuf, 0, 0);
		$cr->paint;
		$cr->show_page;

		undef $surface;
		undef $cr;

	} elsif ($filetype eq 'ps') {

		print "Saving file $filename, $filetype\n" if $self->{_common}->get_debug;

		#0.8? => 72 / 90 dpi
		my $surface = Cairo::PsSurface->create($filename, $pixbuf->get_width * 0.8, $pixbuf->get_height * 0.8);
		my $cr      = Cairo::Context->create($surface);
		$cr->scale(0.8, 0.8);
		Gtk3::Gdk::cairo_set_source_pixbuf($cr, $pixbuf, 0, 0);
		$cr->paint;
		$cr->show_page;

		undef $surface;
		undef $cr;

	} elsif ($filetype eq 'svg') {

		print "Saving file $filename, $filetype\n" if $self->{_common}->get_debug;

		#0.8? => 72 / 90 dpi
		my $surface = Cairo::SvgSurface->create($filename, $pixbuf->get_width * 0.8, $pixbuf->get_height * 0.8);
		my $cr      = Cairo::Context->create($surface);
		$cr->scale(0.8, 0.8);
		Gtk3::Gdk::cairo_set_source_pixbuf($cr, $pixbuf, 0, 0);
		$cr->paint;
		$cr->show_page;

		undef $surface;
		undef $cr;

	} else {

		print "Saving file $filename, $filetype, $quality (using fallback-mode)\n" if $self->{_common}->get_debug;

		#save pixbuf to tempfile
		my ($tmpfh, $tmpfilename) = tempfile();
		$tmpfilename .= '.png';
		if ($pixbuf) {
			$pixbuf->save($tmpfilename, 'png', compression => '9');
		}

		#and convert filetype with imagemagick
		$imagemagick_result = $self->use_imagemagick_to_save($tmpfilename, $filename);
		unlink $tmpfilename;
	}

	#handle possible error messages
	#we use eval to test the pixbuf methods
	#and error messages provided
	#by the imagemagick libs
	if ($@ || $imagemagick_result) {

		#parse filename
		my ($name, $folder, $type) = fileparse($filename, qr/\.[^.]*/);

		my $detailed_message = 'Unknown error';
		if ($@) {
			$detailed_message = $@->message;
		} elsif ($imagemagick_result) {
			$detailed_message = $imagemagick_result;
		}

		#nice error dialog, more detailed messages are shown with a gtk2 expander
		my $response = $self->{_dialogs}->dlg_error_message(
			sprintf($d->get("Error while saving the image %s."),           "'" . $name . $type . "'"),
			sprintf($d->get("There was an error saving the image to %s."), "'" . $folder . "'"),
			undef, undef, undef, undef, undef, undef, $detailed_message
		);
		return FALSE;

	}

	return TRUE;
}

#use imagemagick for all filetypes that are not
#supported by the gdk-pixbuf libs
#e.g. gif
sub use_imagemagick_to_save {
	my $self     = shift;
	my $file     = shift;
	my $new_file = shift;

	#escape filename first
	$file     = quotemeta $file;
	$new_file = quotemeta $new_file;

	my $result = `convert $file $new_file 2>&1`;

	return $result;
}

1;

