#!/usr/bin/perl 
use strict;
use warnings;

# Including the required ESL libaray ( new IVR module)
use ESL::IVR;

# Printng the complex data structure
use Data::Dumper;

# For making the socket connection.
use IO::Socket::INET;

# Specifying IP address and Port number
my $ip = "192.168.1.222"; my $port = '6000';

# Creating a socket
my $sock = new IO::Socket::INET (
	LocalHost => $ip,
	LocalPort => $port,
	Proto     => 'tcp',
	Listen    => 1,
	Reuse     => 1
); 

# Checking the error.
die "Cannot create a socket:$!\n" unless $sock;

# Waiting for the loop to accept the clients or calls.
for(;;) {

	my $new_sock = $sock->accept();

	# Fork the process and parent will wait for new client and child will control our call.
	my $pid = fork();
	if ($pid) {
		close($new_sock);
		next;
	}

	#  Global DTMF buffer
	my $DTMFBuffer= "";

	# Get the host name through the socket.
	my $host = $new_sock->sockhost();

	# Creating object for IVR module.
	my $IVRObject =	new ESL::IVR($new_sock);
	
	# making the log level as 7 
	ESL::eslSetLogLevel(7);
	print Dumper($IVRObject),"\n";

	# From the IVR object get the ESL connection.
	my $con = $IVRObject->{_esl};

	# Set the required variables in the freeswitch.
	$con->sendRecv("myevents");        # Get the events 
	$con->filter("Event-Name","DTMF"); # Filter the events 
	$con->execute("answer");		   # Answer the call 
	$con->setEventLock("true");

	my $Preemption_Flag = 1;
	if($Preemption_Flag) {
		# Set the play back terminators ( This is used to stop the play back when the 
		# specified DTMF event is given.
		$con->execute("set","playback_terminators=0123456789");
	}

	# Set the play back delimiters and play back sleep val and set our own variable.
	$IVRObject->execute("set","playback_delimiter=!");
	$IVRObject->execute("set","playback_sleep_val=1");
	$IVRObject->execute("set","IVRFlag=0");

	# Wait in the loop to set the flag.
	while($con->connected()) {
		if( defined ($IVRObject->getVar('IVRFlag')) && $IVRObject->getVar('IVRFlag') eq '0') {
			last;
		}
	}

	#  playback the voice files 
	$IVRObject->execute("playback","/FreeSWITCH-IVR/VoiceFile/English/iconnectform.wav!/FreeSWITCH-IVR/VoiceFile/English/dial1.wav!/FreeSWITCH-IVR/VoiceFile/English/tcurrform.wav!/FreeSWITCH-IVR/VoiceFile/English/dial2.wav!/FreeSWITCH-IVR/VoiceFile/English/licpayform.wav!/FreeSWITCH-IVR/VoiceFile/English/dial3.wav!/FreeSWITCH-IVR/VoiceFile/English/bsnlform.wav!/FreeSWITCH-IVR/VoiceFile/English/dial4.wav!/FreeSWITCH-IVR/VoiceFile/English/encashform.wav!/FreeSWITCH-IVR/VoiceFile/English/dial5.wav");

	# Set our freeswitch variable for knowing the play back has been done.
	$IVRObject->execute("set","IVRFlag=1");

	# Wait in the loop until the play back has been done. At the same time 
	# check whether any DTMF events are there. This will be helpful for 
	# getting the DTMF events while playing voice files itself.
	while($con->connected()) {

		# Check the flag has to be set 
		if($IVRObject->getVar("IVRFlag") eq '1') { last }

		# Receive the event.
		my $event = $con->recvEventTimed(1);

		# If the event is there and it is DTMF then stored into global buffer.
		if($event) { 
			my $name = $event->getHeader("event-name");
			print "EVENT [$name]\n";
			if ($name eq "DTMF") {
				my $digit = $event->getHeader("dtmf-digit");
				$DTMFBuffer .= $digit; my $duration = $event->getHeader("dtmf-duration");
				print "DTMF digit $digit ($duration)\n";
			}
		}
	}

	# Example response time out and inter digit time out
	my $ResponseTimeOut = 20 * 1000;
	my $interdigittimeout = 10 * 1000 ;
	my ($digit,$ResponseFlag);

	# After play back has been done wait for specified time out to get the DTMF values.
	# The following steps are related to IVR concept.
	# Here if the event is not there handling, based on the condition handle the inter digit 
	# time out and response time out 
	while($con->connected()) {
		my ($event);
		$ResponseFlag = 0 ;
		if (!$DTMFBuffer && $IVRObject->getVar("IVRFlag")) {
			print "Wait for response time out\n";
			$event = $con->recvEventTimed($ResponseTimeOut);
		}elsif($DTMFBuffer && $IVRObject->getVar("IVRFlag")) {
			print "Wait for inter digit time out\n";
			$event = $con->recvEventTimed($interdigittimeout);
		}

		if($event) { 
			my $name = $event->getHeader("event-name");
			print "EVENT [$name]\n";
			if ($name eq "DTMF") {
				$digit = $event->getHeader("dtmf-digit");
				$DTMFBuffer .= $digit;
				my $duration = $event->getHeader("dtmf-duration");
				print "DTMF digit $digit ($duration)\n";
			}
		}else{
			if( ($IVRObject->getVar("IVRFlag")) && !$DTMFBuffer ){
				print "Need to handle the response time out";
			}elsif($IVRObject->getVar("IVRFlag") && $DTMFBuffer){ 
				print "Check the current menu expected digit and based on that handle the inter digit time out\n";
				# For example if it reaches threee digits then exit from the loop.
				if(length($DTMFBuffer) == 3) { last }
			}
		}
	}
	print "Buffer: $DTMFBuffer\n";
	print "BYE\n";
	close($new_sock);
}
