#!/usr/bin/perl
=encoding utf-8

=head1 NAME

kwartz-pkg - Manage Kwartz packages

=head1 VERSION

1.0.0

=cut
our $VERSION= "1.0.0";

=head1 SYNOPSIS

 kwartz-pkg [options] command [parameters ...]
 kwartz-pkg install --missing

=cut

use strict;
use warnings;
use v5.10;
use utf8;

use Hash::Merge::Simple qw/merge/;

#option packages
my %OPTION_TO_PACKAGES = (
    konsole=> [qw/kwartz-agent/],
    -konsolemenu=> 'konsole',
    'wapt_region'=> [qw/wapt-region/],
    'corrium'=> [qw/kwartz-corrium/],
    );

# actions handlers
my $ACTION_DISPATCH = {
    'install'=>\&_do_install,

    #aliases
#    'default' => 'install'
};

use Getopt::Long qw(HelpMessage VersionMessage :config bundling);
use Pod::Usage;
use Data::Dumper;

my $opt_debug=0;
my $opt_verbose=0;
my $opt_quiet;
my $opt_missing;

=head1 DESCRIPTION

B<Ce programme> permet de réaliser diverses opérations sur les paquets Kwartz.
Pour le moment seule la commande L<install> accompagnée de l'option C<--missing>

=cut
_process_options();

my $action = shift @ARGV;

if (defined $action){
    pod2usage("$0: command $action unknown.") unless exists $ACTION_DISPATCH->{$action};
} else {
    pod2usage("$0: command  is mandatory.") unless exists $ACTION_DISPATCH->{default};
    $action = 'default';
}

$action = $ACTION_DISPATCH->{$action};
$action = $ACTION_DISPATCH->{$action} unless ref $action; # for aliases

pod2usage("Internal error.") unless defined $action and ref $action eq 'CODE';

$action->(@ARGV);

exit 0;

=head2 install

L'option L<--missing> doit être présente, sinon sort sans donner d'erreur.

Lorsque l'option L<--missing> est données installe les différents paquets
manquants en prenant en considération plusieurs paramètres. Pour le moment seules 
les options du fichier de clé sont analysées
afin de décider quels sont les paquets nécessaires, en particulier la
présence de l'option konsole ou -konsolemenu. 
Les paquets installés en fonction des options présentes sont les suivants:

=over

=item B<konsole> ou B<-konsolemenu>

C<kwartz-agent>

=back

Ces paquets sont définis pour le moment directement dans le source de la 
commande (voir HASH C<OPTION_TO_PACKAGES>. Un mécanisme plus souple pourra être envisagé.

=cut
sub _do_install{
    # silently exits unless option --missing is given (see DESCRIPTION)
    exit unless $opt_missing; 

    # we can't directly 'use Kwartz::Key' because kwartz-core is not guaranted to be up to date
    my $key = eval {
        require Kwartz::Key;
        Kwartz::Key->import;
        return Kwartz::Key->default();
    };

    # Kwartz::Key must be available (kwartz-core >= 3.2-12)
    # silently exists if not
    unless ($key){
        _log ("no kwartz key found",1);
        exit 0;
    }

    my %missing = ();
    while (my ($o, $v) = each %OPTION_TO_PACKAGES){
        next unless $key->has_option($o);
        $v = $OPTION_TO_PACKAGES{$v}//[] unless ref $v;
        _log ("option $o found... adding '@$v'",2);
        for my $p (@$v){
            $missing{$p} = 1;
        }
    }

    for my $p (keys %missing){
        my $result = qx(/usr/bin/dpkg-query -W -f='\${Status}' $p 2>/dev/null);
        my (undef,undef,$installed) = split ' ', $result;
        if (defined $installed and $installed eq 'installed'){
            delete $missing{$p};
            _log ("$p already installed... skip it" ,2);
        }
    }

    if (keys %missing){
        my $missing = join(' ', keys %missing);
        _log ("installing missing packages: $missing");
        _system ("/usr/sbin/kwartz-autoupdate -a install $missing >/dev/null 2>&1") ;
    } else {
        _log ("no missing package found",2);
    }
}

=head1 OPTIONS

Cette commande accepte les options suivantes en ligne de commande :

=over

=item B<--missing> 

Utilisé par la commande L<install> pour installer les paquets manquants.

=item B<--help>

Print a brief help message and exits.

=item B<--man>

Prints the manual page and exits.

=item B<-d>

Debug mode: don't execute commands, print them to console

=item B<-v[vvv]>

Sets verbosity level (not used ATM)

=item B<-q> 

quiet mode (not used ATM)

=back

=cut
sub _process_options{
	GetOptions(
        "missing"               => \$opt_missing,
		"d+"					=> \$opt_debug,
		"v+"					=> \$opt_verbose,
		"q+"					=> \$opt_quiet,
        "version"               => sub { VersionMessage() },
		"man"					=> sub {pod2usage(-verbose => 2) },
	    "h|help"				=> sub  {HelpMessage()},
	) or pod2usage(2);
}

sub _system{
    if ($opt_debug){
        say "->".$_[0];
        return 0;
    } else {
        return system $_[0];
    }
}

# _log (message, level=1)
sub _log{
    my ($message, $level) = @_;
    $level = 1 unless defined $level;
    say $message if $level<=$opt_verbose;
}
