#!/usr/bin/env python
'''
Copyright (C) 2010, Digium, Inc.
David Vossel <dvossel@digium.com>
Mark Michelson <mmichelson@digium.com>

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

import sys
import os
import signal
import subprocess
from twisted.application import service, internet
from twisted.internet import reactor, defer
from starpy import manager

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

workingdir = "sip_one_legged_transfer_v6"
testdir = "tests/%s" % workingdir

class AttTransferTest:
    def __init__(self):
        self.last_step = ""
        self.passed = False

        reactor.callWhenRunning(self.run)

        self.ast1 = Asterisk(base=workingdir)
        self.ast1.install_configs("%s/configs/ast1" % (testdir))

    def readResult(self):
        self.logLastStep("Reading results")
        self.ast1.cli_exec("core show locks")   # get lock output in case of deadlock before tearing down.
        self.ast1.cli_exec("core show channels")# if channels are still up for some reason, we want to know that as well
        self.stopProcesses()

        if self.passed == True:
            print 'SIP Attended Transfer Test Passed!'
        else:
            print 'SIP Attended Transfer Test Failed'

        if reactor.running:
            print "Stopping Reactor ..."
            reactor.stop()

    def amiOnConnect(self, ami):
        self.logLastStep("Connected to the AMI")
        self.ami = ami

    def amiLoginError(self, ami):
        self.logLastStep("AMI login failed")
        reactor.callLater(1, self.readResult)

    def amiLogin(self):
        self.logLastStep("Logging in to the AMI")
        self.ami_factory = manager.AMIFactory("user", "mysecret")
        self.ami_factory.login('127.0.0.1', 5038).addCallbacks(self.amiOnConnect, self.amiLoginError)

    def checkBridgeResult(self, result):
        print 'Result', result
        if "bridgedchannel" not in result[0]:
            print "bridgedchannel was not a valid key."
        elif result[0]['bridgedchannel'] == 'SIP/end_b-00000001':
            self.passed = True

        if "link" not in result[0]:
            print "'link' was not a valid key."
        elif result[0]['link'] == 'SIP/end_b-00000001': # check link for older versions of asterisk
            self.passed = True

        if self.passed == True:
            self.logLastStep("Found Bridge!!!")
        else:
            self.logLastStep("Detecting Bridge failed")


    def checkBridgeError(self, reason):
        print reason.getTraceback()
        self.logLastStep("Checking Bridge failed.  Channel did not exist.")
        reactor.callLater(1, self.readResult)

    def amiCheckBridge(self):
        self.logLastStep("Get AMI results")
        self.ami.status('SIP/end_c-00000002').addCallbacks(self.checkBridgeResult, self.checkBridgeError)

    def cCallB(self):
        self.logLastStep("C Calling B")
        self.pjc.stdin.write("m\n")
        self.pjc.stdin.write("sip:[::1]:5066\n")

    def bCallA(self):
        self.logLastStep("B Calling A")
        self.pjb.stdin.write("m\n")
        self.pjb.stdin.write("sip:call_a@[::1]:5060\n")

    def bTransferAToC(self):
        self.logLastStep("B Transfering A to C")
        self.pjb.stdin.write("X\n")
        self.pjb.stdin.write("1\n")

    def startProcesses(self):
        self.logLastStep("Starting Processes")
        self.ast1.start()
        self.pja = subprocess.Popen(['pjsua', '--ipv6', '--local-port=5065',
                                     '--auto-answer=200', '--null-audio'],
                                     stdin=subprocess.PIPE,
                                     stdout=subprocess.PIPE)
        self.pjb = subprocess.Popen(['pjsua', '--ipv6', '--local-port=5066',
                                     '--auto-answer=200', '--null-audio'],
                                     stdin=subprocess.PIPE,
                                     stdout=subprocess.PIPE)
        self.pjc = subprocess.Popen(['pjsua', '--ipv6', '--local-port=5067',
                                     '--auto-answer=200', '--null-audio'],
                                     stdin=subprocess.PIPE,
                                     stdout=subprocess.PIPE)

    def stopProcesses(self):
        self.logLastStep("Stopping Processes")
        self.ast1.stop()
        os.kill(self.pja.pid, signal.SIGKILL)
        os.kill(self.pjb.pid, signal.SIGKILL)
        os.kill(self.pjc.pid, signal.SIGKILL)


    def logLastStep(self, step):
        print step
        self.lastStep = step

    def run(self):

        # start up the processes
        self.startProcesses()

        # call extensions
        self.amiLogin()
        reactor.callLater(5, self.cCallB)
        reactor.callLater(10, self.bCallA)
        reactor.callLater(15, self.bTransferAToC)
        reactor.callLater(20, self.amiCheckBridge)

        # stop and read results after timeout
        reactor.callLater(25, self.readResult)

def main():
    # Run Attended Transfer Test
    att_transfer_test = AttTransferTest()
    reactor.run()
    att_transfer_test.stopProcesses()
    if att_transfer_test.passed != True:
        return 1
    return 0

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

