#!/usr/bin/perl

# Copyright (C) 2006-2007 Warp Networks S.L.
# Copyright (C) 2008-2013 Zentyal S.L.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License, version 2, as
# published by the Free Software Foundation.
#
# This program 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 this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

use strict;
use warnings;

use EBox;
use EBox::Exceptions::Sudo::Command;
use EBox::Exceptions::External;
use EBox::Exceptions::Internal;
use EBox::Global;
use EBox::ProgressIndicator;
use EBox::Sudo;

use TryCatch;

sub _regenSoftwareLists
{
    my $global = EBox::Global->getInstance(1);
    my $software = $global->modInstance('software');
    #causes the cache to be generated
    $software->listUpgradablePkgs(1);
}

EBox::init();

my $progressId          = pop @ARGV;
my $progressIdParamName = pop @ARGV; # unused
my @packages            = @ARGV;

my $progress = EBox::ProgressIndicator->retrieve($progressId);
$progress->started() or die('progress executable is not running');

my $webAdminMod = EBox::Global->getInstance()->modInstance('webadmin');

my ($retValue, $errorMsg, $pid) = (0, '', 0);
try {
    my $fifo = '/var/lib/zentyal/apt-install.pipe';

    #Clean fifo
    EBox::Sudo::silentRoot("rm $fifo");
    EBox::Sudo::silentRoot("mkfifo $fifo");

    $webAdminMod->disableRestartOnTrigger();

    EBox::info('Starting package installation process');

    $pid = fork();
    if ($pid == 0) {
        # Child code
        EBox::Sudo::root(EBox::Config::scripts('software') . "apt-wrapper install @packages");
        exit(0);
    }

    my $break = 0;
    my ($read, $text, $oldText);
    do {
        unless (open ($read, '<',  $fifo)){
            throw EBox::Exceptions::Internal("Error opening fifo <$fifo> - $!");
        }
        my $firstLine = '';
        my $lastLine = '';
        while ($text = <$read>) {
            if ($text eq $oldText) {
                last;
            }
            unless ($firstLine) {
                $firstLine = $text;
            }

            if ($text eq 'end') {
                $break = 1;
            }
            # TODO: Now apt-wrapper does not send duplicated lines
            # anymore, maybe this check can be safely removed
            unless ($text eq $lastLine) {
                if ($text =~ /^E:\s*(.*)$/) {
                    $errorMsg = $1;
                    EBox::error($errorMsg);
                    $retValue = 1;
                    $break = 1;
                }
                elsif ($text =~ /^ins([0-9]*)/) {
                    $progress->setTotalTicks($1*2);
                }
                elsif ($text =~ /^Get:[0-9]*\s(.*)/){
                    $progress->setMessage("Downloading $1");
                }
                elsif ($text =~ /^\s*(Unpacking\s.*)/){
                    $progress->notifyTick();
                    $progress->setMessage($text);
                }
                elsif ($text =~ /^\s*(Setting up\s.*)/){
                    $progress->notifyTick();
                    $progress->setMessage($text);
                }
            }
            $oldText = $firstLine;
            $lastLine = $text;
        }

        close $read;

    } until($break);

    EBox::info('Package installation process finished');
} catch ($e) {
    $retValue = $e->exitValue();
    $errorMsg = $e->stringify();
    EBox::error($errorMsg);
}
$webAdminMod->enableRestartOnTrigger();
if ( $pid != 0 ) {
    waitpid($pid, 0);
    if ( ${^CHILD_ERROR_NATIVE} != 0 ) {
        EBox::error('apt-wrapper install was exited with ' . ${^CHILD_ERROR_NATIVE});
    }
}
try {
    $webAdminMod->reload();
    $progress->setAsFinished($retValue, $errorMsg);
} catch (EBox::Exceptions::External $e) {
    # Ignore if it cannot put as finished since it's possible it
    # is already destroyed. Why?
    EBox::warn("$progressId does not exist");
}

_regenSoftwareLists(); # XXX maybe this could be put bef_ the end of progress
                       # indicator to avoid problems
exit $retValue;

1;
