#! /usr/bin/perl

=head1 NAME

printers_edit - edit a printers access list

=head1 SYNOPSIS

 https://server/schulkonsole/printers_edit

=head1 DESCRIPTION

C<printers_edit> provides a possibility to edit a printers access list
-- the room or the hosts list. It is usually invoked from C<printers>.
The HTML template is printers_edit.tt.

=head2 Template variables

Additionally to the variables of Schulkonsole::Session C<printers_edit>
provides the following variables:

=over

=cut

use strict;
use utf8;
use lib '/usr/share/schulkonsole';
use open ':utf8';
use Net::CUPS;
use Net::CUPS::Destination;
use Schulkonsole::Encode;
use Schulkonsole::Files;
use Schulkonsole::Session;


my $this_file = 'printers_edit';



my $sk_session = new Schulkonsole::Session($this_file);
if (not $sk_session->get_password()) {
	my $q = new CGI;
	my $url = $q->url( -full => 1 );

	# we send cookies over secure connections only
	if ($url =~ s/^http:/https:/g) {
		$sk_session->redirect($url);
	} else {
		$sk_session->exit_with_login_page($this_file);
	}
}

my $q = $sk_session->query();


my $cups = new Net::CUPS;
my @destinations = $cups->getDestinations();      # existing printers
my $printers = eval { Schulkonsole::Config::printers(); }; # configured printers
$printers = {} if $@;
my $id = $sk_session->userdata('id');
my $password = $sk_session->get_password();


my $edit_printer;
eval {
foreach my $destination (@destinations) {
	my $printer = $destination->getName();

	if ($q->param("${printer}_rooms")) {	# init rooms
		$edit_printer = $printer;

		my $rooms = Schulkonsole::Config::rooms();
		my @rooms_selected_array;
		my @rooms_deselected_array;
		foreach my $room (sort keys %$rooms) {
			if (    exists $$printers{$printer}
			    and $$printers{$printer}{rooms}{$room}) {
				push @rooms_selected_array, $room;
			} else {
				push @rooms_deselected_array, $room;
			}
		}

=item C<editrooms>

True if the rooms list is edited

=cut

		$sk_session->set_var('editrooms', 1);

=item C<roomsselected>

An array with the rooms selected for the printer

=cut

		$sk_session->set_var('roomsselected', \@rooms_selected_array);

=item C<roomsdeselected>

An array with the rooms not selected for the printer

=cut

		$sk_session->set_var('roomsdeselected', \@rooms_deselected_array);

		last;
	} elsif ($q->param("${printer}_hosts")) {	# init hosts
		$edit_printer = $printer;

		my $hosts = Schulkonsole::Config::hosts();

		my @hosts_selected_array;
		my @hosts_deselected_array;
		foreach my $host (sort keys %$hosts) {
			if (    exists $$printers{$printer}
			    and $$printers{$printer}{hosts}{$host}) {
				push @hosts_selected_array, $host;
			} else {
				push @hosts_deselected_array, $host
					unless $$printers{$printer}{rooms}{$$hosts{$host}};
			}
		}

=item C<hostsselected>

An array with the hosts selected for the printer

=cut

		$sk_session->set_var('hostsselected', \@hosts_selected_array);

=item C<hostsdeselected>

An array with the hosts not selected for the printer

=cut

		$sk_session->set_var('hostsdeselected', \@hosts_deselected_array);

		last;
	} elsif (   $q->param("${printer}_roomselect")
	         or $q->param("${printer}_roomdeselect")) {	# edit rooms
		$edit_printer = $printer;

		my %rooms_selected;
		foreach my $room ($q->param('roomsselected')) {
			$rooms_selected{$room} = 1;
		}

		if ($q->param("${printer}_roomselect")) {
			foreach my $room ($q->param('roomselect')) {
				$rooms_selected{$room} = 1;
			}
		} else {
			foreach my $room ($q->param('roomdeselect')) {
				$rooms_selected{$room} = 0;
			}
		}


		my $rooms = Schulkonsole::Config::rooms();

		my @rooms_selected_array;
		my @rooms_deselected_array;
		foreach my $room (sort keys %$rooms) {
			if ($rooms_selected{$room}) {
				push @rooms_selected_array, $room;
			} else {
				push @rooms_deselected_array, $room;
			}
		}
		$sk_session->set_var('editrooms', 1);
		$q->delete('roomsselected');
		$sk_session->set_var('roomsselected', \@rooms_selected_array);
		$sk_session->set_var('roomsdeselected', \@rooms_deselected_array);

		last;
	} elsif (   $q->param("${printer}_hostselect")
	         or $q->param("${printer}_hostdeselect")) {	# edit hosts
		$edit_printer = $printer;

		my %hosts_selected;
		foreach my $host ($q->param('hostsselected')) {
			$hosts_selected{$host} = 1;
		}

		if ($q->param("${printer}_hostselect")) {
			foreach my $host ($q->param('hostselect')) {
				$hosts_selected{$host} = 1;
			}
		} else {
			foreach my $host ($q->param('hostdeselect')) {
				$hosts_selected{$host} = 0;
			}
		}


		my $hosts = Schulkonsole::Config::hosts();

		my @hosts_selected_array;
		my @hosts_deselected_array;
		foreach my $host (sort keys %$hosts) {
			if ($hosts_selected{$host}) {
				push @hosts_selected_array, $host;
			} else {
				push @hosts_deselected_array, $host
					unless $$printers{$printer}{rooms}{$$hosts{$host}};
			}
		}
		$q->delete('hostsselected');
		$sk_session->set_var('hostsselected', \@hosts_selected_array);
		$sk_session->set_var('hostsdeselected', \@hosts_deselected_array);

		last;
	} elsif ($q->param("${printer}_acceptrooms")) {
		my %rooms_selected;
		foreach my $room ($q->param('roomsselected')) {
			$rooms_selected{$room} = 1;
		}

		my @printer_rooms;
		my $rooms = Schulkonsole::Config::rooms();
		foreach my $room (keys %$rooms) {
			push @printer_rooms, $room if $rooms_selected{$room};
		}


		my $lines = new_printer_lines_room($printer, \@printer_rooms);
		my $id = $sk_session->userdata('id');
		my $password = $sk_session->get_password();
		Schulkonsole::Files::write_printers_file(
			$id, $password,
			$lines);
		Schulkonsole::Files::import_printers($id, $password);

		$sk_session->set_status_redirect($sk_session->d()->get(
			'Änderungen übernommen'), 0);
	} elsif ($q->param("${printer}_accepthosts")) {
		my %hosts_selected;
		foreach my $host ($q->param('hostsselected')) {
			$hosts_selected{$host} = 1;
		}

		my @warnings;
		my @printer_hosts;
		my $hosts = Schulkonsole::Config::hosts();
		foreach my $host (keys %$hosts) {
			next unless $hosts_selected{$host};

			if ($$printers{$printer}{rooms}{$$hosts{$host}}) {
				push @warnings, sprintf($sk_session->d()->get(
					'%s ist schon über Raum %s zugänglich'),
					$host, $$hosts{$host});
			} else {
				push @printer_hosts, $host;
			}
		}


		my $lines = new_printer_lines_host($printer, \@printer_hosts);
		my $id = $sk_session->userdata('id');
		my $password = $sk_session->get_password();
		Schulkonsole::Files::write_printers_file(
			$id, $password,
			$lines);
		Schulkonsole::Files::import_printers($id, $password);

		$sk_session->set_status_redirect(join(', ', @warnings,
			$sk_session->d()->get('Änderungen übernommen')), 0);
	}
}
};
if ($@) {
	$sk_session->standard_error_handling($this_file, $@);
}



if (not $edit_printer) {
	my $url = $q->url( -full => 1 );

	$url =~ s/$this_file$/printers/g;
	$sk_session->redirect($url);
}


=item C<printer>

The name of the printer

=cut

$sk_session->set_var('printer', $edit_printer);


$sk_session->print_page("$this_file.tt", $this_file);



sub new_printer_lines_room {
	my $printer = shift;
	my $rooms = shift;

	@$rooms = ('-') unless @$rooms;

	my @lines;
	my $done = 0;
	if (open PRINTERS, '<',
	         Schulkonsole::Encode::to_fs($Schulkonsole::Config::_printers_file))
	{

		while (<PRINTERS>) {
			my ($conf_printer, $conf_rooms, $conf_hosts) = split /\s+/;
			if ($conf_printer eq $printer) {
                            if (@$rooms[0] ne '-' or (defined $conf_hosts and $conf_hosts ne '-')) {
				push @lines,
				     "$printer\t" . join(',', @$rooms) . "\t$conf_hosts\n";
                            }
                            $done = 1;
                            last;
			} else {
				push @lines, $_;
			}
		}
		while (<PRINTERS>) {
			push @lines, $_;
		}
		
		close PRINTERS;
	}
	
	if (not $done) {
		push @lines, "$printer\t" . join(',', @$rooms) . "\t\n";
	}


	return \@lines;
}




sub new_printer_lines_host {
	my $printer = shift;
	my $hosts = shift;

	@$hosts = ('-') unless @$hosts;

	my @lines;
	my $done = 0;
	if (open PRINTERS, '<',
	         Schulkonsole::Encode::to_fs($Schulkonsole::Config::_printers_file))
	{

		while (<PRINTERS>) {
			my ($conf_printer, $conf_rooms, $conf_hosts) = split /\s+/;
			if ($conf_printer eq $printer) {
                            if (@$hosts[0] ne '-' or (defined $conf_rooms and $conf_rooms ne '-')) {
				push @lines,
				     "$printer\t$conf_rooms\t" . join(',', @$hosts) . "\n";
                            }
                            $done = 1;
                            last;
			} else {
				push @lines, $_;
			}
		}
		while (<PRINTERS>) {
			push @lines, $_;
		}

		close PRINTERS;
	}

	if (not $done) {
		push @lines, "$printer\t-\t" . join(',', @$hosts) . "\n";
	}


	return \@lines;
}



=back

=head2 Form fields

=over

=item C<${printer}_roomselect>

Move marked rooms from deselected to selected

=item C<${printer}_roomdeselect>

Move marked rooms from selected to deselected

=item C<roomselect>

List of marked selected rooms

=item C<roomdeselect>

List of marked deselected rooms

=item C<roomsselected>

List of all selected rooms

=item C<${printer}_acceptrooms>

Accept changes to list

=item C<${printer}_hostselect>

Move marked hosts from deselected to selected

=item C<${printer}_hostdeselect>

Move marked hosts from selected to deselected

=item C<hostselect>

List of marked selected hosts

=item C<hostdeselect>

List of marked deselected hosts

=item C<hostsselected>

List of all selected hosts

=item C<${printer}_accepthosts>

Accept changes to list

=back

