#!/usr/bin/perl -w

use Asterisk::AMI::Common;
use Getopt::Long;

open STDERR, '>/dev/null';

# Set some default
my $host = '127.0.0.1';
my $port = '5038';
my $user = 'zabbixagent';
my $secret = 'zabbixsecret';
my $what = 'sip_peers';

GetOptions(
    "host=s"         => \$host,
    "port=s"         => \$port,
    "user=s"         => \$user,
    "secret=s"       => \$secret,
    "what=s"         => \$what
);

our $ast = Asterisk::AMI::Common->new(
              PeerAddr => $host,
              PeerPort => $port,
              Username => $user,
              Secret  =>  $secret
          );

die "Unable to connect to asterisk manager" unless ($ast);


sub help{
    print<<"EOF";

usage: $0 --host=asterisk.domain.tld --port=5038 --user=manager --secret=azerty --what=sip_peers

--what can take the following argument:

  * sip_peers: number of connected sip peers
  * max_latency: highest latency of connected sip_peers
  * channels: total number of active channels
  * internal_calls: number of active internal calls
  * outgoing_calls: number of active outgoing calls (external)
  * incoming_calls: number of active incoming calls (external)
  * external_calls: number of external calls (in + out)
  * duration_internal: actual highest duration of internal calls
  * duration_external: actual highest duration of external calls

EOF
}

if ($what eq 'sip_peers'){
    print get_connected_peers_num('sip');
}
elsif ($what eq 'max_latency'){
    print get_max_peer_latency();
}
elsif($what eq 'channels'){
    print get_active_channels_num();
}
elsif ($what eq 'internal_calls'){
    print get_internal_call_num();
}
elsif ($what eq 'outgoing_calls'){
    print get_outgoing_call_num();
}
elsif ($what eq 'incoming_calls'){
    print get_incoming_call_num();
}
elsif ($what eq 'external_calls'){
    print get_outgoing_call_num() + get_incoming_call_num();
}
elsif ($what eq 'duration_internal'){
    print get_max_duration_internal();
}
elsif ($what eq 'duration_external'){
    print get_max_duration_external();
}
else{
    help();
    $ast->disconnect();
    exit (1);
}

$ast->disconnect();
exit(0);

# Return the number of connected peers for
# the specified protocol (only SIP supporteed for now)
sub get_connected_peers_num{
    my $proto = shift;
    my $peers;
    if ($proto eq 'sip'){
        $peers = get_sip_peers();
    }
    else{
        return 'unsupported protocol';
    }
    my $num = 0;
    foreach my $peer (keys %{$peers}){
        my $status = $peers->{$peer}->{'Status'};
        $num++ if ($status =~ m/^OK/);
    }
    return $num;
}

# Return the list of SIP peers (as a hashref)
sub get_sip_peers{
    return $ast->sip_peers();
}

# Return the highest latency of all the peers
sub get_max_peer_latency{
    my $peers = get_sip_peers();
    my $latency = 0;
    foreach my $peer (keys %{$peers}){
        my $status = $peers->{$peer}->{'Status'};
        $status =~ /\((\d+)\sms\)/;
        $latency = $1 if ($1 > $latency);
    }
    return $latency;
}

# Return channels list as a hashref
sub get_channels(){
    return $ast->channels();
}

# Return the number of channels 
sub get_active_channels_num{
    my $channels = get_channels();
    my $num = 0;
    foreach my $chan (keys %{$channels}){
        $num++;
    }
    return $num;
}

# Return the number of active channels
sub get_up_channels_num{
    my $channels = get_channels();
    my $num = 0;
    foreach my $chan (keys %{$channels}){
        my $status = $channels->{$chan}->{'State'};
        $num++ if ($status eq 'Up');
    }
    return $num;
}

# Return the number of outgoing calls
sub get_outgoing_call_num{
    my $channels = get_channels();
    my $num = 0;
    foreach my $chan (keys %{$channels}){
        my $context = $channels->{$chan}->{'Context'};
        my $status = $channels->{$chan}->{'State'};
        $num++ if ($context eq 'macro-dialout-trunk' and $status eq 'Up');
    }
    return $num;
}

# Return the number of incoming calls
sub get_incoming_call_num{
    my $channels = get_channels();
    my $num = 0;
    foreach my $chan (keys %{$channels}){
        my $context = $channels->{$chan}->{'Context'};
        my $status = $channels->{$chan}->{'State'};
        $num++ if ($context =~ /^from\-(trunk|pstn|zaptel|dahdi)/ and $status eq 'Up');
    }
    return $num;
}

# Return the number of internal calls
sub get_internal_call_num{
    my $channels = get_channels();
    my $num = 0;
    foreach my $chan (keys %{$channels}){
        my $context = $channels->{$chan}->{'Context'};
        my $status = $channels->{$chan}->{'State'};
        $num++ if (($context eq 'macro-dial' or $context eq 'from-internal') and $status eq 'Up');
    }
    return $num
}

# Return the max duration of current internal calls
sub get_max_duration_internal{
    my $channels = get_channels();
    my $max = 0;
    foreach my $chan (keys %{$channels}){
        my $dur = $channels->{$chan}->{'Seconds'};
        my $context = $channels->{$chan}->{'Context'};
        $max = $dur if (($context eq 'macro-dial' or $context eq 'from-internal') and $dur > $max);
    }
    return $max
}

# Return the max duration of current external calls (in or out)
sub get_max_duration_external{
    my $channels = get_channels();
    my $max = 0;
    foreach my $chan (keys %{$channels}){
        my $dur = $channels->{$chan}->{'Seconds'};
        my $context = $channels->{$chan}->{'Context'};
        $max = $dur if (($context eq 'macro-dialout-trunk' or $context =~ /^from\-(trunk|pstn|zaptel|dahdi)/) and $dur > $max);
    }
    return $max
}

