#!/usr/bin/env python
'''
Copyright (C) 2010-2014, Digium, Inc.
Erin Spiceland <espiceland@digium.com>
Matt Jordan <mjordan@digium.com>

This program is free software, distributed under the terms of
the GNU General Public License Version 2.
'''

import sys
import os
import time
import logging

from twisted.internet import reactor
from starpy import fastagi

sys.path.append("lib/python")
from asterisk.test_case import TestCase

LOGGER = logging.getLogger(__name__)

testdir = "tests/fastagi"

class FastAGIHangupTest(TestCase):
    def __init__(self):
        super(FastAGIHangupTest, self).__init__()

        self.passed = False
        self.timeout = 30
        self.test = 1

        # Listen for results from dialplan
        self.create_fastagi_factory()
        self.agi = None

        self.create_asterisk(base_configs_path="%s/configs" % testdir)

    def on_hangup_failure(self, reason):
        LOGGER.error('Could not hangup: %s' % reason.getTraceback())

    def on_failure(self, reason):
        LOGGER.info("Channel is not active. Hangup succeeded.")
        self.passed = True
        self.read_result()

    def on_hangup(self, status):
        self.test = 2
        self.fastagi_connect(self.agi)

    def finish_test(self, status):
        LOGGER.info("Channel is still up! Status is %s - maybe the channel is "
                    "still attempting to hangup..." % status)
        LOGGER.info("Testing for closed channel again.")

        def __try_again():
            """Try finishing again later"""
            self.agi.channelStatus(agi.variables['agi_channel']
                ).addCallback(self.finish_test2).addErrback(self.on_failure)

        reactor.callLater(__try_again, 5)            

    def finish_test2(self, status):
        LOGGER.error("Channel is still up! Status is %s" % status)
        self.passed = False
        self.read_result()

    # This gets invoked by the dialplan when the call is answered
    # Hangup via fastagi and test channel status
    def fastagi_connect(self, agi):
        self.agi = agi
        if self.test == 1:
            LOGGER.info("Connection established.")
            return agi.hangup().addCallback(self.on_hangup).addErrback(
                self.on_hangup_failure)
        elif self.test == 2:
            LOGGER.info("Testing for closed channel.")
            # We expect this call to fail, as channelStatus()
            # cannot query a dead channel
            return agi.channelStatus(agi.variables['agi_channel']
                ).addCallback(self.finish_test).addErrback(self.on_failure)

    def read_result(self):
        self.agi.finish()
        self.stop_reactor()
        if self.passed is True:
            LOGGER.info("Test Success")
        else:
            LOGGER.error("Failed")

    def launch_test(self):
        LOGGER.info("Originating call to begin test.")
        self.ast[0].cli_originate("Local/503@agitest extension echo@agitest")

    def run(self):
        super(FastAGIHangupTest, self).run()
        self.launch_test()

def main():
    test = FastAGIHangupTest()
    reactor.run()
    if test.passed is not True:
        return 1

    return 0

if __name__ == "__main__":
    sys.exit(main() or 0)
