#!/usr/bin/env python
#
# Copyright (c) 2013, 2014 Matt Behrens <matt@zigg.com>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.


from twisted.internet.defer import inlineCallbacks
from twisted.python import log

from octothorpe.asyncagi import AsyncAGIChannel, AsyncAGIProtocol


"""Captures DTMF and plays it back.

For this to work, you need a dialplan hook on an incoming extension
that passes the call to AsyncAGI, like so:

    [context]
    exten => 400,1,AGI(agi:async)
    same => n,Hangup

(See agihello for more information on how AsyncAGI works.)

In this example, we introduce the use of inlineCallbacks, a Twisted
feature, to consolidate call logic into a single method.

"""


def _printDict(d):
    for key in sorted(d.keys()):
        print '\t%r: %r' % (key, d[key])



class AnswererChannel(AsyncAGIChannel):
    def asyncAGIStarted(self, context, extension, priority, env):
        print 'Call received: ', context, extension, priority
        if context == 'default' and extension == '403':
            print 'It is ours'
            self.handleCall()


    @inlineCallbacks
    def handleCall(self):
        result = yield self.sendAGI('EXEC Playback beep')
        if result[0] != 0:
            raise Exception(result)

        digits = yield self.captureDTMF(5)
        for digit in digits:
            if digit == '#':
                digit = 'pound'
            elif digit == '*':
                digit = 'star'

            result = yield self.sendAGI('EXEC Playback digits/%s' % digit)
            if result[0] != 0:
                raise Exception(result)

        result = yield self.sendAGI('HANGUP')
        if result[0] != 1:
            raise Exception(result)


class Answerer(AsyncAGIProtocol):
    channelClass = AnswererChannel

    def __init__(self, username, secret):
        self.username = username
        self.secret = secret
        AsyncAGIProtocol.__init__(self)


    def bannerReceived(self, banner):
        AsyncAGIProtocol.bannerReceived(self, banner)
        self.loginMD5(self.username, self.secret)


    def eventReceived(self, event, message):
        print 'Event received:', event
        _printDict(message)
        AsyncAGIProtocol.eventReceived(self, event, message)


    def responseReceived(self, response, message, body):
        print 'Response received:', response
        _printDict(message)
        if body:
            print '\tbody: %r' % (body,)
        AsyncAGIProtocol.responseReceived(self, response, message, body)


    def sendAction(self, action, fields):
        print 'Sending action:', action
        _printDict(fields)
        return AsyncAGIProtocol.sendAction(self, action, fields)


if __name__ == '__main__':
    from twisted.internet import reactor
    from twisted.internet.protocol import ClientFactory
    from twisted.python import log
    from sys import stderr

    class AnswererFactory(ClientFactory):
        def buildProtocol(self, addr):
            return Answerer('manager', 'secret')

    log.startLogging(stderr)
    reactor.connectTCP('172.20.64.100', 5038, AnswererFactory())
    reactor.run()


# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
