#!__PERL__
# -*- perl -*-

# Copyright (c) 2005 by Jeff Weisberg
# Author: Jeff Weisberg <argus @ tcp4me.com>
# Created: 2005-Dec-10 15:18 (EST)
# Function: vxml cgi
#
# $Id$

# QQQ - authentication? access control?

use lib('__LIBDIR__');
use lib('bin');
package Argus::Web::VXML;
use Argus::Ctl;
use Argus::Encode;
use CGI;
use Fcntl;
use Socket;
use POSIX;
require "conf.pl";
use strict;
use vars qw($datadir);

my $cgi  = CGI->new();
my $url  = $cgi->url( -path_info => 1 );
my $obj  = decode( $cgi->param('object') ) || 'Top';
my $func = $cgi->param('func') || 'browse';
my $wtp  = $cgi->param('wtp');

my $argusd = argus_connect();
browse($obj)                  if $func eq 'browse';
notifs()                      if $func eq 'notifs';  # list all unacked
notify( $cgi->param('idno') ) if $func eq 'notify';  # data on specific
notack( $cgi->param('idno') ) if $func eq 'ack';
argus_disconnect($argusd);
exit;

################################################################

sub vxml_top {

    print $cgi->header();
    my $title = $obj || $func;
    
    print <<EOV;
<?xml version="1.0" encoding="UTF-8"?>
<vxml version="2.0">
  <!-- Argus: $title -->

  <property name="termchar" value=" "/>
  <property name="interdigittimeout" value="1s"/>
  <noinput count="3"><disconnect/></noinput>
  <nomatch>invalid selection.</nomatch>

  <script><![CDATA[
    function saydtmf(dtmf){
	if( dtmf == '#' ){ return 'pound' }
	if( dtmf == '*' ){ return 'star' }
	return dtmf;
    }	   
  ]]></script>

EOV
    ;

    unless( $wtp ){
	print <<EOV;
  <form><block>
    <prompt>Welcome to Argus.</prompt>
    <goto next="#mainmenu"/>
  </block></form>

EOV
    ;
    }
}

sub vxml_bottom {

    print <<EOV;
</vxml>
EOV
    ;
}

sub vxml_mainmenu {
    my $obj = shift;

    my $uniq   = getparam( $obj, 'vxml_long_name' );
    my $status = getparam( $obj, 'ovstatus' );
    my $type   = getparam( $obj, 'type' );
    my $parent = getparam( $obj, 'parents::0::unique' );
    $parent ||= 'Top';
    
    print <<EOV;
  <menu id="mainmenu">
    <prompt bargein="true">
      $type $uniq is $status.
      <enumerate><value expr="_prompt"/>, press <value expr="saydtmf(_dtmf)"/>. </enumerate>
    </prompt>
    <choice dtmf="1" next="#details">For further details</choice>
EOV
    ;
    print qq{    <choice dtmf="2" next="#children">To browse children</choice>\n}
      if $type eq 'Group';
    print qq{    <choice dtmf="3" next="$url?func=browse;object=$parent;wtp=1">To go up a level</choice>\n}
      unless $obj eq 'Top';
    
    print <<EOV;
    <choice dtmf="0" next="$url?wtp=1">To browse to Top level</choice>
    <choice dtmf="*" next="$url?func=notifs;wtp=1">For the Alerts menu</choice>
  </menu>

EOV
    ;
}

sub vxml_nokids {
    my $obj = shift;

    print <<EOV;
  <form id="children">
    <block>
      <prompt>Object has no children</prompt>
      <goto next="#mainmenu"/>
    </block>
  </form>
EOV
    ;
}

sub vxml_children {
    my $obj = shift;

    my($rh, $ra) = $argusd->command_a( func   => 'getchildrenparamnr',
			      object => $obj,
			      param  => 'vxml_short_name',
			      );
    
    return vxml_nokids( $obj ) if $rh->{resultcode} != 200;
    delete $rh->{resultcode};
    delete $rh->{resultmsg};
    return vxml_nokids( $obj ) unless @$ra;

    print <<EOV;
  <menu id="children">
    <prompt bargein="true">
      <enumerate>For <value expr="_prompt"/>, press <value expr="saydtmf(_dtmf)"/>. </enumerate>
    </prompt>
EOV
    ;

    my $dtmf = 1;
    foreach my $x (@$ra){
	my($xob, $xnm) = @$x;
	print qq{    <choice dtmf="$dtmf" next="$url?func=browse;object=$xob;wtp=1">$xnm</choice>\n};
	$dtmf ++;
    }

    print <<EOV;
    <choice dtmf="#" next="#mainmenu">the previous menu</choice>
    <choice dtmf="0" next="$url?wtp=1">the Top level</choice>
    <choice dtmf="*" next="$url?func=notifs;wtp=1">the Alerts menu</choice>
  </menu>

EOV
    ;
}

sub vxml_details {
    my $obj = shift;

    my $uniq   = getparam( $obj, 'vxml_short_name' );
    my $descr  = getparam( $obj, 'vxml_descr' );
    my $status = getparam( $obj, 'ovstatus' );
    my $type   = getparam( $obj, 'type' );
    my $reason = getparam( $obj, 'srvc::reason' );
    my $since  = getparam( $obj, 'transtime' );

    $reason = "because $reason" if $reason;
    $since  = saytime($since);

    print <<EOV;
  <menu id="details">
    <prompt bargein="true">
      $uniq became $status at $since. $descr $reason
      <enumerate>For <value expr="_prompt"/>, press <value expr="saydtmf(_dtmf)"/>. </enumerate>
    </prompt>
    <!-- RSN - more choices ... -->
    <choice dtmf="#" next="#mainmenu">the previous menu</choice>	  
    <choice dtmf="0" next="$url?wtf=1">the Top level</choice>
    <choice dtmf="*" next="$url?func=notifs;wtp=1">the Alerts menu</choice>
  </menu>

EOV
    ;
    
}

sub browse {
    my $obj = shift;

    vxml_top();
    vxml_mainmenu( $obj );
    vxml_details( $obj );
    vxml_children( $obj );
    vxml_bottom();
}

sub notifs {
    
    my $r = $argusd->command_raw( func  => 'notify_list',
				  which => 'unacked',
				  );
    my @notif;
    while( $_ = $argusd->nextline() ){
	chop;
	last if /^$/;
	push @notif, $_;
    }

    my $nnotif = @notif;
    vxml_top();

    print <<EOV;
  <menu id="mainmenu">
    <prompt>
      There are $nnotif un-acked alerts
      <enumerate><value expr="_prompt"/>, press <value expr="saydtmf(_dtmf)"/>. </enumerate>
    </prompt>
    <choice dtmf="1" next="#list">For a list of un-acked alerts</choice>
    <choice dtmf="2" next="#enter">For a specific alert by eye-dee number</choice>
    <choice dtmf="3" next="$url?func=ack;idno=all;wtp=1">To ack all alerts</choice>
    <!-- anywhere else? -->
    <choice dtmf="0" next="$url?wtf=1">the Top level</choice>
  </menu>

  <menu id="list">
    <prompt>
      <enumerate><value expr="_prompt"/>, press <value expr="saydtmf(_dtmf)"/>. </enumerate>
    </prompt>
EOV
    ;
    
    my $dtmf = 1;
    foreach my $not (@notif){
	my($idno, $st, $time, $obj, $msg) = split /\s+/, $not;
	my $name = getparam( $obj, 'vxml_long_name' );
	print qq{    <choice dtmf="$dtmf" next="$url?func=notify;idno=$idno;wtp=1">Number $idno, $name</choice>\n};
	$dtmf ++;
    }
    
    print <<EOV;
    <choice dtmf="#" next="#mainmenu">the previous menu</choice>
    <choice dtmf="0" next="$url?wtf=1">the Top level</choice>
    <choice dtmf="*" next="#mainmenu">the Alerts menu</choice>	
  </menu>
      
  <form id="enter">
    <property name="termchar" value="#"/>
    <field name="idno" type="digits">
      <prompt>
        Enter the alert eye-dee number followed by the pound key.
      </prompt>
    </field>
    <filled>
      <goto expr="'$url?wtp=1;func=notify;idno=' + idno"/>
    </filled>
  </form>

EOV
    ; 

    vxml_bottom();
}

sub notify {
    my $idno = shift;

    my $r = $argusd->command( func => 'notify_detail',
			      idno => $idno );
    my $obj   = $r->{object};
    my $name  = getparam( $obj, 'vxml_long_name' );
    my $when  = saytime($r->{created});
    my $acked = ($r->{state} eq 'acked') ? 'This alert has been acked.' : '';
    vxml_top();
    print <<EOV;
  <menu name="mainmenu">    
    <prompt>
      Alert $idno. $name became $r->{objstate} at $when. $acked
      <enumerate><value expr="_prompt"/>, press <value expr="saydtmf(_dtmf)"/>. </enumerate>
    </prompt>
    <choice dtmf="1" next="$url?func=ack;idno=$idno;wtp=1">To ack this alert</choice>
    <choice dtmf="2" next="$url;wtp=1">For $name</choice>
    <choice dtmf="0" next="$url?wtf=1">For the Top level</choice>
    <choice dtmf="*" next="$url?func=notifs;wtp=1">For the Alerts menu</choice>		  
  </menu>
EOV
    ;

    vxml_bottom();
}

sub notack {
    my $idno = shift;

    vxml_top();
    
    my $r = $argusd->command( func => 'notify_ack',
			      idno => $idno,
			      user => 'argusvxml' );

    my $what = ($idno eq 'all') ? 'All Alerts have been acked' : "Alert $idno has been acked";
    my $msg  = ($r->{resultcode} == 200) ?
	$what : "Ack error: $r->{resultmsg}";
    
    print <<EOV;
  <menu>
    <prompt>
      $msg
      <enumerate>For <value expr="_prompt"/>, press <value expr="saydtmf(_dtmf)"/>. </enumerate>
    </prompt>
    <choice dtmf="0" next="$url;wtp=1">the Top level</choice>
    <choice dtmf="*" next="$url?func=notifs;wtp=1">the Alerts menu</choice>      
  </menu>
EOV
    ;
    vxml_bottom();
}

sub saytime {
    my $time = shift;

    strftime '%H:%M %B %d', localtime($time);
}

sub getparam {
    my $obj   = shift;
    my $param = shift;

    my $r = $argusd->command( func   => 'getparam',
			      object => $obj,
			      param  => $param );
    $r->{value};
}

sub argus_connect {
    my $argusd = Argus::Ctl->new( "$datadir/control",
			   retry  => 1,
			   encode => 1,
			   decode => 1,
			   who    => 'argusvxml' );
    $argusd;
}

sub argus_disconnect {
    my $argusd = shift;
    $argusd->disconnect();
}

