#! /usr/bin/perl

=head1 NAME

linbo_new - create a new LINBO start.conf.*

=head1 SYNOPSIS

 https://server/schulkonsole/linbo_new

=head1 DESCRIPTION

C<linbo_new> lets the user create a new start.conf.* file for a workstation
group.
The HTML template is linbo_new.tt.

=head2 Template variables

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

=over

=cut

use strict;
use utf8;
use lib '/usr/share/schulkonsole';
use Schulkonsole::Session;
use Schulkonsole::Config;
use Schulkonsole::Linbo;


my $this_file = 'linbo_new';



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 $groups = Schulkonsole::Config::linbogroups();
my $templates_os = Schulkonsole::Linbo::get_templates_os();

my $example = Schulkonsole::Linbo::example_start_confs();

eval {
SWITCHCOMMAND: {

$q->param('copy') and do {
	my $src = $q->param('src');

	if (not $src) {
		$sk_session->set_status(
			$sk_session->d()->get('Keine Gruppe ausgewählt'),
			1);
		last SWITCHCOMMAND;
	}
	if (not $$groups{$src}) {
		$sk_session->set_status(sprintf(
				$sk_session->d()->get('Gruppe %s existiert nicht'), $src),
			1);
		last SWITCHCOMMAND;
	}

	my $dest = $q->param('dest');
	$dest =~ s/\s*(\S+)\s*/$1/;
	if (not $dest) {
		$sk_session->set_status(
			$sk_session->d()->get('Keine Zielgruppe angegeben'),
			1);
		last SWITCHCOMMAND;
	}
	if ($dest !~ /^[a-z\d_]+$/) {
		$sk_session->set_status(
			$sk_session->d()->get('Ungültiger Zielgruppenname'),
			1);
		last SWITCHCOMMAND;
	}

	Schulkonsole::Linbo::copy_start_conf(
		$sk_session->userdata('id'),
		$sk_session->get_password(),
		$src, $dest);

	$groups = Schulkonsole::Config::linbogroups();
	if ($$groups{$dest}) {
		$sk_session->set_status(
			$sk_session->d()->get('Konfigurationsdatei kopiert'), 0);
	} else {
		$sk_session->set_status(
			$sk_session->d()->get('Konfigurationsdatei konnte nicht kopiert werden'), 1);
	}

	last SWITCHCOMMAND;
};

$q->param('create') and do {

	my ($group) = $q->param('group') =~ /^\s*(.+?)\s*$/;
	$group = lc $group;
	my ($systemtype) = $q->param('systemtype') =~ /^\s*(.+?)\s*$/;
	my ($disksize_value) = $q->param('disksize_value') =~ /^\s*(.+?)\s*$/;
	my ($disksize_unit) = $q->param('disksize_unit') =~ /^\s*(.+?)\s*$/;
	my $disk_size = $disksize_value . $disksize_unit;
	my ($device) = $q->param('device') =~ /^\s*(.+?)\s*$/;
	my ($os_template_1) = $q->param('os1') =~ /^\s*(.+?)\s*$/;
	my ($os_size_1) = $q->param('size1') =~ /^\s*(.+?)\s*$/;
	my ($os_template_2) = $q->param('os2') =~ /^\s*(.+?)\s*$/;
	my ($os_size_2) = $q->param('size2') =~ /^\s*(.+?)\s*$/;
	my ($os_template_3) = $q->param('os3') =~ /^\s*(.+?)\s*$/;
	my ($os_size_3) = $q->param('size3') =~ /^\s*(.+?)\s*$/;
	my ($os_template_4) = $q->param('os4') =~ /^\s*(.+?)\s*$/;
	my ($os_size_4) = $q->param('size4') =~ /^\s*(.+?)\s*$/;


	my @errors;
	if ($group !~ /^[a-z\d_]+$/) {
		push @errors, $sk_session->d()->get('Ungültiger Gruppenname');
		$sk_session->mark_input_error('group');
	} elsif ($$groups{$group}) {
		push @errors, $sk_session->d()->get(
		              	'Rechnergruppenname schon vergeben');
		$sk_session->mark_input_error('group');
	}

	if (not $systemtype) {
		push @errors, $sk_session->d()->get('Ungültiger Systemtyp');
		$sk_session->mark_input_error('systemtype');
	} elsif ($systemtype !~ /bios|bios64|efi32|efi64/) {
		push @errors, $sk_session->d()->get('Unbekannter Systemtyp');
		$sk_session->mark_input_error('systemtype');
	}
	
	if (not $disk_size) {
		push @errors, $sk_session->d()->get(
		              	'Keine Festplattengröße angegeben');
		$sk_session->mark_input_error('disksize');
	} elsif ($disk_size !~ /^\d+(k|M|G|T)?$/) {
		push @errors, $sk_session->d()->get(
		              	'Festplattengröße muss eine Zahl (wahlweise mit Einheit) sein');
		$sk_session->mark_input_error('disksize');
	}

	if ($device !~ /^(sda|mmcblk0)$/) {
		push @errors, $sk_session->d()->get(
		              	'Unbekannter Festplattencontroller');
		$sk_session->mark_input_error('device');
	}


	my $os_size_total = 0;

	if ($os_template_1) {
		if (not $$templates_os{$os_template_1}) {
			push @errors, sprintf($sk_session->d()->get(
			                      	'Template %s nicht vorhanden'),
			                      $os_template_1);
			$sk_session->mark_input_error('os1');
		}

		if (not $os_size_1) {
			$os_size_1 = '10M';
		} elsif ($os_size_1 !~ /^\d+(k|M|G|T)?$/) {
			push @errors, sprintf($sk_session->d()->get(
			                      	'Größe für Betriebssystem 1 muss eine Zahl (wahlweise mit Einheit) sein'),
			                      $os_template_1);
			$sk_session->mark_input_error('os1');
			$os_size_1 = '10M';
		}
	} elsif (not $os_size_1) {
		$os_size_1 = '10M';
	}

	my $os_size_1test = Schulkonsole::Linbo::partsize_to_kB($os_size_1);
	$os_size_total += $os_size_1test;

	if ($os_template_2) {
		if (not $$templates_os{$os_template_2}) {
			push @errors, sprintf($sk_session->d()->get(
			                      	'Template %s nicht vorhanden'),
			                      $os_template_2);
			$sk_session->mark_input_error('os2');
		}

		if (not $os_size_2) {
			$os_size_2 = '10M';
		} elsif ($os_size_2 !~ /^\d+(k|M|G|T)?$/) {
			push @errors, sprintf($sk_session->d()->get(
			                      	'Größe für Betriebssystem 2 muss eine Zahl (wahlweise mit Einheit) sein'),
			                      $os_template_2);
			$sk_session->mark_input_error('os2');
			$os_size_2 = '10M';
		}
	} elsif (not $os_size_2) {
		$os_size_2 = '10M';
	}

	$os_size_total += Schulkonsole::Linbo::partsize_to_kB($os_size_2);

	if ($os_template_3) {
		if (not $$templates_os{$os_template_3}) {
			push @errors, sprintf($sk_session->d()->get(
			                      	'Template %s nicht vorhanden'),
			                      $os_template_3);
			$sk_session->mark_input_error('os3');
		}

		if (not $os_size_3) {
			$os_size_3 = '10M';
		} elsif ($os_size_3 !~ /^\d+(k|M|G|T)?$/) {
			push @errors, sprintf($sk_session->d()->get(
			                      	'Größe für Betriebssystem 3 muss eine Zahl (wahlweise mit Einheit) sein'),
			                      $os_template_3);
			$sk_session->mark_input_error('os3');
			$os_size_3 = '10M';
		}
	} elsif (not $os_size_3) {
		$os_size_3 = '10M';
	}

	$os_size_total += Schulkonsole::Linbo::partsize_to_kB($os_size_3);

	if ($os_template_4) {
		if (not $$templates_os{$os_template_4}) {
			push @errors, sprintf($sk_session->d()->get(
			                      	'Template %s nicht vorhanden'),
			                      $os_template_4);
			$sk_session->mark_input_error('os4');
		}

		if (not $os_size_4) {
			$os_size_4 = '10M';
		} elsif ($os_size_4 !~ /^\d+(k|M|G|T)?$/) {
			push @errors, sprintf($sk_session->d()->get(
			                      	'Größe für Betriebssystem 4 muss eine Zahl (wahlweise mit Einheit) sein'),
			                      $os_template_4);
			$sk_session->mark_input_error('os4');
			$os_size_4 = '10M';
		}
	} elsif (not $os_size_4) {
		$os_size_4 = '10M';
	}

	$os_size_total += Schulkonsole::Linbo::partsize_to_kB($os_size_4);

	if ($os_size_total * 1.7 >= Schulkonsole::Linbo::partsize_to_kB($disk_size)) {
		push @errors, $sk_session->d()->get(
		              	'Festplatte für die gewählte Gruppenkonfiguration zu klein');
		$sk_session->mark_input_error('disksize');
	}


	if (@errors) {
		$sk_session->set_status(join(', ', @errors), 1);
	} else {
		Schulkonsole::Linbo::create_start_conf_from_template(
			$sk_session->userdata('id'),
			$sk_session->get_password(),
			$group,
			$systemtype,
			$ENV{SERVER_ADDR},
			$device,
			$os_template_1, $os_size_1,
			$os_template_2, $os_size_2,
			$os_template_3, $os_size_3,
			$os_template_4, $os_size_4);
		$sk_session->set_status(
			$sk_session->d()->get('Konfigurationsdatei erstellt'), 0);
	}

	last SWITCHCOMMAND;
};

$q->param('create_from_example') and do {

	my ($selection) = $q->param('selected_example');
	my ($group) = $q->param('group') =~ /^\s*(.+?)\s*$/;
	$group = lc $group;
	my ($disksize_value) = $q->param('disksize_value') =~ /^\s*(.+?)\s*$/;
	my ($disksize_unit) = $q->param('disksize_unit') =~ /^\s*(.+?)\s*$/;
	my $disk_size = $disksize_value . $disksize_unit;
	my ($device) = $q->param('device') =~ /^\s*(.+?)\s*$/;

	my @errors;
	if (not exists $$example{$selection}) {
		push @errors, $sk_session->d()->get('Ungültiges Beispiel');
	}
	
	if ($group !~ /^[a-z\d_]+$/) {
		push @errors, $sk_session->d()->get('Ungültiger Gruppenname');
		$sk_session->mark_input_error('group');
	} elsif ($$groups{$group}) {
		push @errors, $sk_session->d()->get(
		              	'Rechnergruppenname schon vergeben');
		$sk_session->mark_input_error('group');
	}

	if (not $disk_size) {
		push @errors, $sk_session->d()->get(
		              	'Keine Festplattengröße angegeben');
		$sk_session->mark_input_error('disksize');
	} elsif ($disk_size !~ /^\d+(k|M|G|T)?$/) {
		push @errors, $sk_session->d()->get(
		              	'Festplattengröße muss eine Zahl (wahlweise mit Einheit) sein');
		$sk_session->mark_input_error('disksize');
	}

	if ($device !~ /^(sda|mmcblk0)$/) {
		push @errors, $sk_session->d()->get(
		              	'Unbekannter Festplattencontroller');
		$sk_session->mark_input_error('device');
	}


	if (@errors) {
		$sk_session->set_status(join(', ', @errors), 1);
	} else {
		Schulkonsole::Linbo::create_start_conf_from_example(
			$sk_session->userdata('id'),
			$sk_session->get_password(),
			$selection,
			$group,
			$ENV{SERVER_ADDR},
			$device,
			$disk_size);
		$sk_session->set_status(
			$sk_session->d()->get('Konfigurationsdatei erstellt'), 0);
	}

	last SWITCHCOMMAND;
};

}
};
if ($@) {
	$sk_session->standard_error_handling($this_file, $@);
}


=item C<groups>

List of all groups that have a start.conf.*

=cut

$sk_session->set_var('groups', [ sort keys %$groups ]);


my @templates_os;
foreach my $template_name (sort keys %$templates_os) {
	push @templates_os, $template_name;
}

=item C<hastemplates>

True if there are any tempaltes

=cut

$sk_session->set_var('hastemplates', @templates_os);



=item C<templatesos>

List of all templates

=cut

$sk_session->set_var('templatesos', \@templates_os);



=item C<systemtype>

Specify systemtype to default 'bios'

=cut

if(not defined $sk_session->param('systemtype')) {
	$sk_session->set_var('systemtype','bios');
}

=item C<hasexamples>

True if there are any examples

=cut

$sk_session->set_var('hasexamples', %$example );

=item C<example>

Hash of all examples with explanations

=cut

$sk_session->set_var('example', $example );


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


=back

=head2 Form fields


=head3 Parameters to copy start.conf.*-files

=over

=item C<copy>, C<src>, and C<dest>

If C<copy> is selected start.conf.C<src> is copied to start.conf.C<dest>.

=back


=head3 Parameters to create new start.conf.* from templates

=over

=item C<group>

=item C<disksize>

=item C<device>

One of C<sda> or C<hda>.

=item C<os1>

Windowstemplate from which to create section for first OS, created from array
in session variable C<templatesoswin>.

=item C<size1>

Size of partition on which the first OS is to be installed.

=item C<os2>

Windows template from which to create section for second OS, created from array
in session variable C<templatesoswin>.

=item C<size2>

Size of partition on which the second OS is to be installed.

=item C<os3>

GNU/Linux-Template from which to create section for third OS, created from array
in session variable C<templatesosnowin>.

=item C<size3>

Size of partition on which the third OS is to be installed.

=item C<os4>

GNU/Linux template from which to create section for third OS, created from array
in session variable C<templatesosnowin>.

=item C<size4>

Size of partition on which the third OS is to be installed.

=item C<create>

Submit button to create new start.conf.* file

=back

=head3 Parameters to create new start.conf.* from examples

=over

=item C<group>

=item C<disksize>

=item C<device>

One of C<sda> or C<hda>.

=item C<create_from_example>

Submit button to create new start.conf.* file from example

=back
