#!/usr/bin/env python
'''
Copyright (C) 2010, Digium, Inc.
Matthias Nick <mnick86@gmail.com>

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

import sys
import logging
from twisted.internet import reactor

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

logger = logging.getLogger(__name__)


class CallParkingTest(TestCase):
    def __init__(self):
        TestCase.__init__(self)

        self.ami_count = 0
        self.parking_var = "exten"

        if AsteriskVersion() >= AsteriskVersion('12'):
            self.parking_var = "parkingspace"

        # Initial parked call subtest.
        self.expected_space = 701
        self.request_exten = 101

        # Clear parked call subtest completion stage flags.
        self.got_AMI_UnParkedCall = False
        self.ast1_event = False
        self.ast2_event = False

        # Create two Asterisk instances ...
        self.create_asterisk(2)

    def check_result(self):
        if not self.got_AMI_UnParkedCall:
            return
        if not self.ast1_event:
            return
        if not self.ast2_event:
            return

        # Parked call subtest completed successfully.
        # Clear parked call subtest completion stage flags.
        self.got_AMI_UnParkedCall = False
        self.ast1_event = False
        self.ast2_event = False

        if self.request_exten == 101:
            # Start next parked call subtest.
            self.expected_space = 702
            self.request_exten = 102
            self.initiate_call_to_park()
            return

        if self.request_exten == 102:
            # Start next parked call subtest.
            self.expected_space = 703
            self.request_exten = 103
            self.initiate_call_to_park()
            return

        # All parked call subtests completed successfully.
        logger.info("Test completed successfully")
        self.passed = True
        self.stop_reactor()

    # Initiate test call to park.
    def initiate_call_to_park(self):
        logger.info("Initiating test call for " + str(self.request_exten))
        self.ast[0].cli_originate("Local/9876@ast2/n extension " + str(self.request_exten) + "@ast2")

    # Initiate a call to retrieve the parked call.
    def get_parkedcall(self):
        logger.info("Fetching parked call at " + str(self.expected_space))
        self.ast[1].cli_originate("IAX2/ast1/" + str(self.expected_space) + " extension retrieve@ast1")

    # Called when got UnParkedCall AMI event
    def ast1_unparkedcall(self, ami, event):
        exten = event.get(self.parking_var)
        if not exten or exten != str(self.expected_space):
            logger.info("Call not retrieved from expected space " + str(self.expected_space))
            self.stop_reactor()
            return
        logger.info("Parked call retrieved from exten: " + str(exten))

        self.got_AMI_UnParkedCall = True
        self.check_result()

    # Called when got ParkedCall AMI event
    def ast1_parkedcall(self, ami, event):
        exten = event.get(self.parking_var)
        if not exten or exten != str(self.expected_space):
            logger.info("Call not parked in expected space " + str(self.expected_space))
            self.stop_reactor()
            return
        logger.info("Call parked at exten: " + str(exten))

        self.get_parkedcall()

    # Called when got UserEvent AMI event from Ast2
    def ast2_userevent(self, ami, event):
        status = event.get("status")
        logger.info("ast2_userevent status: " + str(status))
        if status != "SUCCESS":
            self.stop_reactor()
            return

        self.ast2_event = True
        self.check_result()

    # Called when got UserEvent AMI event from Ast1
    def ast1_userevent(self, ami, event):
        status = event.get("status")
        logger.info("ast1_userevent status: " + str(status))
        if status != "SUCCESS":
            self.stop_reactor()
            return

        self.ast1_event = True
        self.check_result()

    # This is called for each AMI connection established.
    def ami_connect(self, ami):
        # Add AMI event triggers
        if ami.id == 0:
            self.ami[ami.id].registerEvent("ParkedCall", self.ast1_parkedcall)
            self.ami[ami.id].registerEvent("UnParkedCall", self.ast1_unparkedcall)
            self.ami[ami.id].registerEvent("UserEvent", self.ast1_userevent)
        elif ami.id == 1:
            self.ami[ami.id].registerEvent("UserEvent", self.ast2_userevent)

        # Initiate test when both AMI connections are established.
        self.ami_count += 1
        if self.ami_count == 2:
            self.initiate_call_to_park()

    # This is called when the reactor has started running.
    def run(self):
        TestCase.run(self)
        self.create_ami_factory(2)


def main():
    # Run CallParking Test
    test = CallParkingTest()
    test.start_asterisk()
    reactor.run()
    test.stop_asterisk()
    if test.passed:
        logger.info("Test passed")
        return 0
    return 1

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


# vim:sw=4:ts=4:expandtab:textwidth=79
