#!/usr/bin/perl

use strict;
use warnings;
use lib './lib';

use English qw(-no_match_vars);
use Getopt::Long;
use Pod::Usage;
use XML::TreePP;

use FusionInventory::Agent::Task::NetInventory;
use FusionInventory::Agent::Tools;
use FusionInventory::Agent::Logger;

my %types = (
    1 => 'COMPUTER',
    2 => 'NETWORKING',
    3 => 'PRINTER',
    4 => 'STORAGE',
    5 => 'POWER',
    6 => 'PHONE',
    7 => 'VIDEO',
);

my $options = {
    debug => 0,
    threads => 1
};

my %setup = (
    confdir => './etc',
    datadir => './share',
    libdir  => './lib',
    vardir  => './var',
);

GetOptions(
    $options,
    'model=s',
    'type=s',
    'host=s@',
    'file=s',
    'community=s',
    'credentials=s',
    'threads=i',
    'timeout=i',
    'control',
    'debug+',
    'help',
    'version',
) or pod2usage(-verbose => 0);

if ($options->{version}) {
  print "NetInventory task $FusionInventory::Agent::Task::NetInventory::VERSION\n";
  exit 0;
}
pod2usage(-verbose => 0, -exitval => 0) if $options->{help};

pod2usage(
    -message => "no host nor file given, aborting\n", -verbose => 0
) unless $options->{host} or $options->{file};

warn "deprecated option model, ignoring\n" if $options->{model};

my @devices = map {
        {
            ID           => 0,
            IP           => $_,
            FILE         => $options->{file},
            AUTHSNMP_ID  => 1,
            MODELSNMP_ID => 1
        }
    } @{$options->{host}};

my $credentials = { ID => 1 };

if ($options->{type}) {
    pod2usage(
        -message => "invalid type '$options->{type}', aborting\n",
        -verbose => 0
    ) unless any { $options->{type} eq $_ } values %types;
    map { $_->{TYPE} = $options->{type} } @devices;
}

if ($options->{community}) {
    $credentials->{COMMUNITY} = $options->{community};
} elsif (defined $options->{credentials}) {
    foreach my $parameter (split(',', $options->{credentials})) {
        my ($key, $value) = split(':', $parameter);
        my $newkey =
            $key eq 'authpassword' ? 'AUTHPASSPHRASE' :
            $key eq 'privpassword' ? 'PRIVPASSPHRASE' :
                                     uc($key);
        $credentials->{$newkey} = $value;
    }
} else {
    $credentials->{COMMUNITY} = 'public';
}

my $verbosity =
    $options->{debug} == 0 ? LOG_INFO   :
    $options->{debug} == 1 ? LOG_DEBUG  :
    $options->{debug} == 2 ? LOG_DEBUG2 :
                             LOG_DEBUG2 ;

my $inventory = FusionInventory::Agent::Task::NetInventory->new(
    %setup,
    target => FusionInventory::Agent::Task::NetInventory::Target->new(),
    logger => FusionInventory::Agent::Logger->new(verbosity => $verbosity)
);

$inventory->{jobs} = [
    {
        params => {
            PID           => 1,
            THREADS_QUERY => $options->{threads},
            TIMEOUT       => $options->{timeout},
        },
        devices     => \@devices,
        credentials => [ $credentials ]
    }
];

$inventory->{client} =
    FusionInventory::Agent::Task::NetInventory::Client->new(
        control => $options->{control}
    );
# TODO: need to be dropped the day we will depend on agent >= 2.3.0
$inventory->{deviceid} = 'foo';

$inventory->run();

package FusionInventory::Agent::Task::NetInventory::Client;

sub new {
    my ($class, %params) = @_;

    return bless {
        control => $params{control}
    }, $class;
}

sub send {
    my ($self, %params) = @_;

    # don't display control message by default
    return unless $self->{control}
        or $params{message}->{h}->{CONTENT}->{DEVICE};

    print $params{message}->getContent();
}

package FusionInventory::Agent::Task::NetInventory::Target;

sub new {
    my ($class) = @_;

    return bless {}, $class;
}

sub getUrl {
    my ($self, %params) = @_;

    ## no critic (ExplicitReturnUndef)
    return undef;
}

__END__

=head1 NAME

fusioninventory-netinventory - Standalone network inventory

=head1 SYNOPSIS

fusioninventory-netinventory [options] [--host <host>|--file <file>]

  Options:
    --host host    host to inventorize (use multiple time to inventorize more hosts)
    --file         snmpwalk output file
    --community    community string (default: public)
    --credentials  SNMP credentials
    --timeout val  SNMP timeout (default: 15s)
    --threads nb   number of invenroty threads (default: 1)
    --control      output control messages
    --debug        debug output (execution traces)
    -h --help      print this message and exit
    --version      print the task version and exit

=head1 DESCRIPTION

F<fusioninventory-netinventory> allows to run a network inventory task without
a GLPI server.
