#!/usr/bin/perl

use Data::Dumper;

use strict;
use warnings;

use Snap;

setup();

my $conf = readconf();
my $templates = templates( $conf );
my $template = $ARGV[0] || Snap->error( 1, 'Failed to supply template' );
my $sources = Snap::Sources->new( $conf->{'sources'} );
my @basepkgs = qw( snap-base coreutils dash );
my @packages = ();
my $rootfs;
my $preinst;
my $rootpw;
my $postinst;
my $pid;
my $stat;
my $virtfs;
my $dialog;

if ( ! $snap->{'target'} ) {
	Snap->error( -1, 'A target must be specified with -t' );
	}

if ( ! $templates->{$template} ) {
	Snap->error( -1, "$template: Invalid template" );
	}

$rootfs = "$conf->{'snapinstall'}{'templatedir'}/$template/rootfs";
$preinst = "$conf->{'snapinstall'}{'templatedir'}"
	. "/$template/preinst";
$postinst = "$conf->{'snapinstall'}{'templatedir'}"
	. "/$template/postinst";

if ( -f $preinst ) {
	pipe( my $reader, my $writer ) ||
		Snap->error( int( $! ), "pipe(): $!" );

	if ( $pid = fork() ) {
		close( $writer );
		}
	else {
		close( $reader );
		open( STDERR, '>&', $writer );
		exec( $preinst ) || die( $! );

		exit;
		}

	waitpid( $pid, 0 );
	$stat = $? >> 8;

	while ( readline( $reader ) ) {
		if ( $_ =~ /^([a-zA-Z]+)=\s*(.*)$/ ) {
			$ENV{$1} = $2;
			}
		}

	close( $reader );
	}

$sources->readpkgs();

foreach my $pkgname ( @basepkgs ) {
	my $package = $sources->latest( $pkgname );

	$package->depends( $sources, \@packages );

	if ( ! grep( $_ eq $package->{'name'}, @packages ) ) {
		push( @packages, $package );
		}
	}

foreach my $pkgname ( @{$templates->{$template}{'packages'}} ) {
	my $package = $sources->latest( $pkgname ) ||
		Snap->error( 1, "$pkgname: Unable to find package" );

	if ( grep( $_->{'name'} eq $pkgname, @packages ) ) {
		next;
		}

	$package->depends( $sources, \@packages );

	if ( ! grep( $_ eq $package->{'name'}, @packages ) ) {
		push( @packages, $package );
		}
	}

open( $dialog, "|dialog --title ' Downloading Packages ' --gauge '' 8 70 0" );
select( $dialog );

foreach my $package ( @packages ) {
	if ( $package->{'path'} =~ /https*:\/\// ) {
		( my $filename = $package->{'path'} ) =~ s/.*\///;

		if ( -f $snap->{'pkgdir'} . "/$filename" ) {
			$package->{'path'} = $snap->{'pkgdir'} . "/$filename";
			}
		elsif ( -f "/var/lib/snap/packages/$filename" ) {
			$package->{'path'} = "/var/lib/snap/packages/$filename";
			}
		else {
			Snap->httpget( $package->{'path'},
				"$snap->{'pkgdir'}/$filename", 0644,
				{ dialog => 1 } );

			$package->{'path'} = "$snap->{'pkgdir'}/$filename";
			}
		}
	}

select( STDOUT );
close( $dialog );

if ( -d $rootfs && ! Snap->dirempty( $rootfs ) ) {
	if ( $pid = fork() ) {
		waitpid( $pid, 0 );
		$stat = $? >> 8;
		}
	else {
#		print "\nCopying rootfs files\n";
#		exec( "cp -va '$rootfs'/* $snap->{'target'}" );
		exec( "cp -a '$rootfs'/* $snap->{'target'}" );
		}

	if ( $stat ) {
		Snap->error( $stat, "Failed to copy rootfs" );
		}
	}

open( $dialog, "|dialog --title ' Installing Packages ' --gauge '' 8 70 0" );
select( $dialog );

foreach my $package ( @packages ) {
	if ( ! $virtfs ) {
		$virtfs = virtfs( 'mount' );
		}

#	print "\n";

	$package->install( $sources, { dialog => 1 } );
	}

select( STDOUT );
close( $dialog );

print "\033[2J";
print "\033[0;0H";

trigger();

if ( -f $postinst ) {
	my $tmpscript = "/var/lib/snap/postinst";

	open( my $fh, '<', $postinst ) || Snap->error( int( $! ),
		"Failed to open $postinst" );
	open( my $wh, '>', "$snap->{'target'}/$tmpscript" ) ||
		Snap->error( int( $! ), "Failed to open $tmpscript" );
	chmod( 0755, "$snap->{'target'}/$tmpscript" );

	while ( <$fh> ) {
		print $wh $_;
		}

	close( $wh );
	close( $fh );

	if ( $pid = fork() ) {
		waitpid( $pid, 0 );
		$stat = $? >> 8;
		}
	else {
		if ( $> ) {
			exec( "fakeroot fakechroot /usr/sbin/chroot "
				. "$snap->{'target'} $tmpscript" );
			}
		else {
			exec ( "chroot $snap->{'target'} $tmpscript" );
			}
		}

	if ( $stat ) {
		Snap->error( $stat, "Failed to execute $tmpscript" );
		}
	}

if ( $virtfs ) {
	virtfs( 'umount' );
	}
