###################################################
#
#  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::Screenshot::Workspace;

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

use Shutter::Screenshot::Main;
use Shutter::Screenshot::History;
use Data::Dumper;
our @ISA = qw(Shutter::Screenshot::Main);

#Glib
use Glib qw/TRUE FALSE/;

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

sub new {
	my $class = shift;

	#call constructor of super class (shutter_common, include_cursor, delay, notify_timeout)
	my $self = $class->SUPER::new(shift, shift, shift, shift);

	$self->{_selected_workspace}   = shift;
	$self->{_vpx}                  = shift;
	$self->{_vpy}                  = shift;
	$self->{_current_monitor_only} = shift;

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

#~ sub DESTROY {
#~ my $self = shift;
#~ print "$self dying at\n";
#~ }

sub workspaces {
	my $self = shift;

	my $d = $self->{_sc}->get_gettext;

	my $active_workspace = $self->{_wnck_screen}->get_active_workspace;

	#valid workspace?
	return TRUE unless $active_workspace;

	my $active_vpx = $active_workspace->get_viewport_x;
	my $active_vpy = $active_workspace->get_viewport_y;

	#create shutter region object
	my $sr = Shutter::Geometry::Region->new();

	#variables to save the pixbuf
	my $output = undef;
	my $pixbuf = undef;

	my $wspaces_region = Cairo::Region->create;
	my @pixbuf_array;
	my @rects_array;
	my $row    = 0;
	my $column = 0;
	my $height = 0;
	my $width  = 0;
	foreach my $space (@{$self->{_workspaces}}) {
		next unless defined $space;

		#compiz
		if ($self->{_wm_manager_name} =~ /compiz/i) {

			#calculate viewports with size of workspace
			my $vpx = $space->get_viewport_x;
			my $vpy = $space->get_viewport_y;

			my $n_viewports_column = int($space->get_width / $self->{_wnck_screen}->get_width);
			my $n_viewports_rows   = int($space->get_height / $self->{_wnck_screen}->get_height);

			#rows
			for (my $j = 0 ; $j < $n_viewports_rows ; $j++) {

				#columns
				for (my $i = 0 ; $i < $n_viewports_column ; $i++) {
					my @vp = ($i * $self->{_wnck_screen}->get_width, $j * $self->{_wnck_screen}->get_height);

					#set coordinates
					$self->{_vpx} = $vp[0];
					$self->{_vpy} = $vp[1];

					#and disable workspace
					$self->{_selected_workspace} = undef;

					#capture viewport
					$pixbuf = $self->workspace(TRUE, TRUE);

					my $rect = {x=>$width, y=>$height, width=>$pixbuf->get_width, height=>$pixbuf->get_height};
					$wspaces_region->union_rectangle($rect);
					push @pixbuf_array, $pixbuf;
					push @rects_array,  $rect;

					#increase width according to current column
					$width += $pixbuf->get_width;

				}

				#next row
				# > set height to clipbox-height
				# > set width to 0, because we start in column 0 again
				$height = $sr->get_clipbox($wspaces_region)->{height};
				$width  = 0;

			}

			#all other wm manager like metacity etc.
		} else {

			#capture next workspace
			$self->{_selected_workspace} = $space->get_number;

			#~ print "Capturing Workspace: ".$space->get_number." Layout-Row:". $space->get_layout_row ." Layout-Column:". $space->get_layout_column ."\n";
			$pixbuf = $self->workspace(TRUE, TRUE);

			if ($column < $space->get_layout_column) {
				$width += $pixbuf->get_width;
			} elsif ($column > $space->get_layout_column) {
				$width = 0;
			}
			$column = $space->get_layout_column;

			$height = $sr->get_clipbox($wspaces_region)->{height} if ($row != $space->get_layout_row);
			$row    = $space->get_layout_row;

			my $rect = {x=>$width, y=>$height, width=>$pixbuf->get_width, height=>$pixbuf->get_height};
			$wspaces_region->union_rectangle($rect);
			push @pixbuf_array, $pixbuf;
			push @rects_array,  $rect;

		}

	}

	if ($wspaces_region->num_rectangles) {
		$output = Gtk3::Gdk::Pixbuf->new('rgb', TRUE, 8, $sr->get_clipbox($wspaces_region)->{width}, $sr->get_clipbox($wspaces_region)->{height});
		$output->fill(0x00000000);

		#copy images to the blank pixbuf
		my $rect_counter = 0;
		foreach my $pixbuf (@pixbuf_array) {
			$pixbuf->copy_area(0, 0, $pixbuf->get_width, $pixbuf->get_height, $output, $rects_array[$rect_counter]->{x}, $rects_array[$rect_counter]->{y});
			$rect_counter++;
		}
	}

	#this value will be overwritten - restore for history
	$self->{_selected_workspace} = 'all';

	#set history object
	$self->{_history} = Shutter::Screenshot::History->new($self->{_sc});

	#set name of the captured workspace
	#e.g. for use in wildcards
	if ($output =~ /Gtk3/) {
		$self->{_action_name} = $d->get("Workspaces");
	}

	#compiz
	if ($self->{_wm_manager_name} =~ /compiz/i) {
		$self->{_wnck_screen}->move_viewport($active_vpx, $active_vpy);

		#metacity etc.
	} else {
		$active_workspace->activate(Gtk3::get_current_event_time());
	}

	return $output;
}

sub workspace {
	my $self            = shift;
	my $no_active_check = shift || FALSE;
	my $no_finishing    = shift || FALSE;

	my $wrksp_changed = FALSE;

	my $active_workspace = $self->{_wnck_screen}->get_active_workspace;

	#valid workspace?
	return TRUE unless $active_workspace;

	my $active_vpx = $active_workspace->get_viewport_x;
	my $active_vpy = $active_workspace->get_viewport_y;

	#metacity etc
	if (defined $self->{_selected_workspace}) {
		foreach my $space (@{$self->{_workspaces}}) {
			next unless defined $space;
			if ($self->{_selected_workspace} == $space->get_number
				&& ($no_active_check || $self->{_selected_workspace} != $active_workspace->get_number))
			{
				$space->activate(Gtk3::get_current_event_time());
				$wrksp_changed = TRUE;
			}
		}

		#compiz
	} else {
		$self->{_wnck_screen}->move_viewport($self->{_vpx}, $self->{_vpy});
		$wrksp_changed = TRUE;
	}

	#we need a minimum delay of 1 second
	#to give the server a chance to
	#redraw after switching workspaces
	if ($self->{_delay} < 2 && $wrksp_changed) {
		$self->{_delay} = 1;
	}

	my $output = undef;
	if ($self->{_current_monitor_only} || $self->{_gdk_screen}->get_n_monitors <= 1) {
		($output) = $self->get_pixbuf_from_drawable($self->get_root_and_current_monitor_geometry);

		#When there are multiple monitors with different resolutions, the visible area
		#within the root window may not be rectangular (it may have an L-shape, for
		#example). In that case, mask out the areas of the root window which would
		#not be visible in the monitors, so that screenshot do not end up with content
		#that the user won't ever see.
		#
		#comment copied from gnome-screenshot
		#http://svn.gnome.org/viewvc/gnome-utils/trunk/gnome-screenshot/screenshot-utils.c?view=markup
	} elsif ($self->{_gdk_screen}->get_n_monitors > 1) {

		($output) = $self->get_pixbuf_from_drawable($self->get_root_and_geometry, $self->get_monitor_region);

	}

	unless ($no_finishing) {

		#set history object
		$self->{_history} = Shutter::Screenshot::History->new($self->{_sc});

		#set name of the captured workspace
		#e.g. for use in wildcards
		if ($output =~ /Gtk3/) {
			$self->{_action_name} = $self->{_wnck_screen}->get_active_workspace->get_name;
		}

		#metacity etc
		if ($self->{_selected_workspace}) {
			$active_workspace->activate(Gtk3::get_current_event_time()) if $wrksp_changed;

			#compiz
		} else {
			$self->{_wnck_screen}->move_viewport($active_vpx, $active_vpy);
		}

	}

	return $output;
}

sub redo_capture {
	my $self   = shift;
	my $output = 3;
	if (defined $self->{_history} && $self->{_selected_workspace} eq 'all') {
		$output = $self->workspaces();
	} elsif (defined $self->{_history}) {
		$output = $self->workspace();
	}
	return $output;
}

sub get_history {
	my $self = shift;
	return $self->{_history};
}

sub get_error_text {
	my $self = shift;
	return $self->{_error_text};
}

sub get_action_name {
	my $self = shift;
	return $self->{_action_name};
}

1;
