#!/usr/bin/perl

use strict;
use warnings;

use lib './lib';
use setup;

use English qw(-no_match_vars) ;
use Getopt::Long;
use Pod::Usage;
use UNIVERSAL::require;

use FusionInventory::Agent::Config;
use FusionInventory::Agent::Version;
use FusionInventory::Agent::Logger;
use FusionInventory::Agent::Inventory;
use FusionInventory::Agent::Task::WMI::Version;

Getopt::Long::Configure( "no_ignorecase" );

my $options = {
    debug => 0
};

GetOptions(
    $options,
    'backend-collect-timeout=s',
    'conf-file=s',
    'config=s',
    'ca-cert-dir=s',
    'ca-cert-file=s',
    'debug+',
    'help',
    'host|h=s',
    'local|l=s',
    'logger=s',
    'logfile=s',
    'no-category=s',
    'no-ssl-check',
    'no-compression|C',
    'pass|p=s',
    'scan-homedirs',
    'scan-profiles',
    'server|s=s',
    'tag|t=s',
    'user|u=s',
    'version'
) or pod2usage(-verbose => 0);

my $PROVIDER = $FusionInventory::Agent::Version::PROVIDER;
my $VERSION  = FusionInventory::Agent::Task::WMI::Version::VERSION;

# Set AGENT_STRING to be included in inventory as VERSIONCLIENT
$FusionInventory::Agent::AGENT_STRING   = "$PROVIDER-WMI-Inventory_v$VERSION";
$FusionInventory::Agent::VERSION_STRING = "$PROVIDER WMI Inventory ($VERSION)";

unshift @{$FusionInventory::Agent::Version::COMMENTS},
    "** THIS IS A DEVELOPMENT RELEASE **"
    if ($FusionInventory::Agent::Version::VERSION =~ /^\d+\.\d+\.(99\d\d|\d+-dev)$/);

if ($options->{version}) {
    map { print $_."\n" }
        lc($PROVIDER) . "-wmi $VERSION",
        "based on $PROVIDER Agent v$FusionInventory::Agent::Version::VERSION",
        @{$FusionInventory::Agent::Version::COMMENTS};
    exit 0;
}

die lc($PROVIDER) . "-wmi only supported under win32 platform\n"
    unless ($OSNAME eq 'MSWin32');

pod2usage(-verbose => 0, -exitstatus => 0)
    if ($options->{help} || !$options->{host});

if ($options->{'conf-file'}) {
    if ($options->{config}) {
        if ($options->{config} ne 'file') {
            print STDERR
                "don't use --conf-file with $options->{config} backend";
            exit 1;
        }
    } else {
        $options->{config} = 'file';
    }
}

# Under win32, registry config is automatically loaded and may populate server target
# So we prefer to explicitly unset server target if only local is wanted without config defined
if ($options->{'local'} && !$options->{'server'} && !$options->{'config'}) {
    $options->{'server'} = "";
}


my $config = FusionInventory::Agent::Config->new(
    options => $options,
);

my $logger = FusionInventory::Agent::Logger->new(config => $config);

# From here we may need to avoid crashes due to not thread-safe Win32::OLE
FusionInventory::Agent::Tools::Win32->require();
FusionInventory::Agent::Tools::Win32::start_Win32_OLE_Worker();
FusionInventory::Agent::Tools::Win32::setupWorkerLogger(config => $config);

# Get targets
my $targets = $config->getTargets(
    logger      => $logger,
    vardir      => $setup{vardir}
);

die "No target defined, aborting\n"
    unless $targets;

FusionInventory::Agent::Task::WMI->require();

foreach my $target (@{$targets}) {
    my $wmitask = FusionInventory::Agent::Task::WMI->new(
        target  => $target,
        logger  => $logger,
        datadir => $setup{datadir},
        config  => $config
    );

    die _error("Connection failure")
        unless $wmitask->connect(%{$options});
    warn _error("Failed to create inventory for ".$target->getName()." ".$target->getType()." target")
        unless $wmitask->run();
}

exit(0);

sub _error {
    my ($failure) = @_;

    my ($error, $message) = FusionInventory::Agent::Tools::Win32::getLastError();

    return "$failure\n" unless $error && $message;

    return sprintf("%s: Err=0x%08X\n%s\n", $failure, $error, $message);
}

__END__

=head1 NAME

fusioninventory-wmi - Win32 remote inventory

=head1 SYNOPSIS

fusioninventory-wmi [options] --host <host> [--user <user>] [--pass <pass>] [--server server|--local path]

  General options:
    --help                         this menu
    -t --tag tag                   tag for the inventoried machine

  Remote machine options:
    -h --host hostname             hostname - mandatory option
    -u --user username             user name
    -p --pass xxxx                 user password

  Target definition options:
    -s --server=URI                send tasks result to a server
    -l --local=PATH                write tasks results locally

  Inventory task options:
    --backend-collect-timeout=TIME timeout for inventory modules execution
                                   (default: 180s)
    --no-category=CATEGORY         do not list given category items
    --scan-homedirs                scan user home directories (false)
    --scan-profiles                scan user profiles (false)

  Network options:
    --ca-cert-dir=DIRECTORY        CA certificates directory
    --ca-cert-file=FILE            CA certificates file
    --no-ssl-check                 do not check server SSL certificate
                                     (false)
    -C --no-compression            do not compress communication with server
                                     (false)

  Logging options:
    --logger=BACKEND               logger backend (stderr)
    --logfile=FILE                 log file

  Configuration options:
    --config=BACKEND               configuration backend
    --conf-file=FILE               configuration file

=head1 EXAMPLES

    % fusioninventory-wmi --host 172.xx.xxx.xxx --user foo --password bar --local=.

=head1 DESCRIPTION

F<fusioninventory-wmi> creates inventory of remote Win32 machine.
It uses the WMI interface of the remote server.
