#
# Manages Plugins for CasparBuster
#
# $Id$
#
#
package CasparBuster::Plugin;

use strict;
use warnings;
use Carp;
use CasparBuster::Env;
use ProjectBuilder::Base;
use ProjectBuilder::Conf;
use Data::Dumper;

# Global vars
# Inherit from the "Exporter" module which handles exporting functions.
#
use vars qw($VERSION $REVISION @ISA @EXPORT);
use Exporter;
#
# Export, by default, all the functions into the namespace of
# any code which uses this module.

our @ISA = qw(Exporter);
our @EXPORT = qw(cb_plugin_load cb_plugin_get);

=pod

=head1 NAME

CasparBuster::Plugin - module dealing with CasparBuster plugin management

=head1 DESCRIPTION

This modules provides functions to allow the management of CasparBuster plugins

=head1 SYNOPSIS

  use CasparBuster::Plugin;

=head1 USAGE

=over 4

=item B<cb_plugin_load>

This function loads all the plugins defined for this CasparBuster environement

=cut

sub cb_plugin_load {

my ($pluginsdir) = pb_conf_get("cbpluginssubdir");
my $cbconfdir = cb_env_confdir()."/$pluginsdir->{$ENV{'PBPROJ'}}";
opendir(DIR,$cbconfdir) || die "Unable to open $cbconfdir: $!";
foreach my $f (readdir(DIR)) {
	next if ($f =~ /^\./);
	# Add on plugins files
	if ($f =~ /\.conf$/) {
		pb_conf_add("$cbconfdir/$f") if (-f "$cbconfdir/$f");
	}
}
closedir(DIR);

my ($flist,$dlist,$dflist,$slist) = pb_conf_get_if("cbpluginfiles","cbplugindirs","cbplugindirsandfiles","cbppkgreload");
if (defined $flist) {
	foreach my $plugin (keys %$flist) {
		foreach my $block (split(/;/,$flist->{$plugin})) {
			pb_log(3,"block : $block\n");
			my ($name,$tmp) = split(/\|/,$block);
			($cbp->{'files'}->{$name}->{'uid'},$cbp->{'files'}->{$name}->{'gid'},$cbp->{'files'}->{$name}->{'mode'}) = split(/\,/,$tmp);
		}
	}
}
if (defined $dlist) {
	foreach my $plugin (keys %$dlist) {
		foreach my $block (split(/;/,$dlist->{$plugin})) {
			pb_log(3,"block : $block\n");
			my ($name,$tmp) = split(/\|/,$block);
			($cbp->{'dirs'}->{$name}->{'uid'},$cbp->{'dirs'}->{$name}->{'gid'},$cbp->{'dirs'}->{$name}->{'mode'}) = split(/\,/,$tmp);
		}
	}
}
if (defined $dflist) {
	foreach my $plugin (keys %$dflist) {
		foreach my $block (split(/;/,$dflist->{$plugin})) {
			pb_log(3,"block : $block\n");
			my ($name,$tmp) = split(/\|/,$block);
			($cbp->{'dirsandfiles'}->{$name}->{'uid'},$cbp->{'dirsandfiles'}->{$name}->{'gid'},$cbp->{'dirsandfiles'}->{$name}->{'mode'}) = split(/\,/,$tmp);
		}
	}
}
if (defined $slist) {
	foreach my $plugin (keys %$slist) {
		foreach my $name (split(/,/,$slist->{$plugin})) {
			$cbp->{'reload'}->{$plugin}->{'restart'} = $name;
		}
	}
}


=item B<cb_plugin_get>

This function adds into the plugin hash, passed as second parameter, the new plugin content based on its name, passed as first parameter.

=cut

sub cb_plugin_get {

my $plugin = shift;
my $cbp = shift;
my $remote = shift;
my $machine = shift;
my $debug = shift;
my $ssh2 = shift;

pb_log(2,"Entering cb_plugin_get for plugin $plugin\n");
my ($flist,$dlist,$dflist,$slist,$plist) = pb_conf_get_if("cbpluginfiles","cbplugindirs","cbplugindirsandfiles","cbppkgreload","cbpluginpkgs");
if ((defined $flist) && (defined $flist->{$plugin}) && ($flist->{$plugin} !~ /^\s*$/)) {
	foreach my $block (split(/;/,$flist->{$plugin})) {
		pb_log(3,"block : $block\n");
		my ($name,$tmp) = split(/\|/,$block);
		($cbp->{$plugin}->{'files'}->{$name}->{'uid'},$cbp->{$plugin}->{'files'}->{$name}->{'gid'},$cbp->{$plugin}->{'files'}->{$name}->{'mode'}) = split(/\,/,$tmp);
	}
}
if ((defined $dlist) && (defined $dlist->{$plugin}) && ($dlist->{$plugin} !~ /^\s*$/)) {
	foreach my $block (split(/;/,$dlist->{$plugin})) {
		pb_log(3,"block : $block\n");
		my ($name,$tmp) = split(/\|/,$block);
		($cbp->{$plugin}->{'dirs'}->{$name}->{'uid'},$cbp->{$plugin}->{'dirs'}->{$name}->{'gid'},$cbp->{$plugin}->{'dirs'}->{$name}->{'mode'}) = split(/\,/,$tmp);
	}
}
if ((defined $dflist) && (defined $dflist->{$plugin}) && ($dflist->{$plugin} !~ /^\s*$/)) {
	foreach my $block (split(/;/,$dflist->{$plugin})) {
		pb_log(3,"block : $block\n");
		my ($name,$tmp) = split(/\|/,$block);
		($cbp->{$plugin}->{'dirsandfiles'}->{$name}->{'uid'},$cbp->{$plugin}->{'dirsandfiles'}->{$name}->{'gid'},$cbp->{$plugin}->{'dirsandfiles'}->{$name}->{'mode'}) = split(/\,/,$tmp);
	}
}
if ((defined $plist) && (defined $plist->{$plugin})) {
	foreach my $name (split(/,/,$plist->{$plugin})) {
		$cbp->{$plugin}->{'pkgs'}->{$name}->{'name'} = $name;
		if ((defined $slist) && (defined $slist->{$name})) {
			$cbp->{$plugin}->{'pkgs'}->{$name}->{'restart'} = $slist->{$name};
		}
	}
} else {
	$cbp->{$plugin}->{'pkgs'}->{$plugin}->{'name'} = $plugin;
}
# Check remotely what conf files are needed for this plugin through its packages
$ssh2 = cb_ssh_init($remote,$machine,$debug) if (not defined $ssh2);

my $chan = $ssh2->channel();
pb_log(3,"DEBUG: SSH2 chan called\n");
confess "Unable to create channel for $remote\@$machine: $!" if (not defined $chan);
if ($debug) {
	pb_log(1,"DEBUG: launching a shell via Net:SSH2 ($remote\@$machine)\n");
}
confess "Unable to launch remote shell through Net:SSH2 ($remote\@$machine)" if (not $chan->shell());
pb_log(3,"DEBUG: SSH2 shell called\n");

foreach my $p (keys $cbp->{$plugin}->{'pkgs'}) {
	# TODO: Do not hardcode rpm
	my $cmd = "sudo rpm -q -c --dump $p";
	pb_log(2,"DEBUG: Calling $cmd\n");
	print $chan "$cmd\n";
	while (<$chan>) {
		my ($name,$d1,$d2,$d3,$mode,$uid,$gid,$dummy) = split(/ /,$_);
		$cbp->{$plugin}->{'files'}->{$name}->{'uid'} = $uid;
		$cbp->{$plugin}->{'files'}->{$name}->{'gid'} = $gid;
		$cbp->{$plugin}->{'files'}->{$name}->{'mode'} = substr($mode,4,);
		pb_log(3,"DEBUG: Found $name");
	}
}

$chan->close();

pb_log(2,"cbp: ".Dumper($cbp)."\n");
return($cbp);
}

1;
