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

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

import sys
import os
import logging

from twisted.internet import reactor

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

LOGGER = logging.getLogger(__name__)

class PickupTest(TestCase):

    def __init__(self):
        TestCase.__init__(self)
        self.firstChannel = None
        self.secondChannel = None
        self.bridgeCount = 0
        self.create_asterisk()

        self.bridgingModel12 = False
        self.bridge = None
        self.firstChannelBridged = False
        self.secondChannelBridged = False
        self.picked_up = False

    def hangup(self, ami):
        self.stop_reactor()

    def check_test_done(self):

        if self.picked_up and (not self.bridgingModel12 or (self.firstChannelBridged and self.secondChannelBridged)):
            self.set_passed(True)
            self.ami[0].hangup(self.firstChannel).addCallback(self.hangup)
            LOGGER.info("Both first and second channel detected; passing test")


    def check_BridgeEnter(self, ami, event):
        channel = event.get('channel')
        bridge = event.get('bridgeuniqueid')
        other_channel = None

        if channel == self.firstChannel:
            self.firstChannelBridged = True
            if self.secondChannel:
                other_channel = self.secondChannel
        else:
            if not self.secondChannel:
                self.secondChannel = channel
            self.secondChannelBridged = True
            other_channel = self.firstChannel

        if self.bridge is not None:
            if bridge != self.bridge:
                LOGGER.error("Channel: '%s' entered bridge '%s', but was expected to enter the '%s' bridge with '%s'" % (channel, bridge, other_channel, self.bridge))
                self.set_passed(False)
        else:
            self.bridge = bridge

        self.check_test_done()

    def check_Bridge(self, ami, event):
        if self.bridgeCount != 0:
            return
        self.bridgeCount += 1

        channel1 = event.get('channel1')
        channel2 = event.get('channel2')

        self.check_test_done()

    def check_Pickup(self, ami, event):
        if not self.secondChannel:
            self.secondChannel = event.get('channel')
        elif self.secondChannel != event.get('channel'):
            LOGGER.error("Channel %s is in Pickup event but is not second channel %s" % (
                event.get('channel'), self.secondChannel))
            self.set_passed(False)
            return

        LOGGER.info("Detected second channel in Pickup: %s" % self.secondChannel)
        self.picked_up = True
        if not self.bridgingModel12:
            self.ami[0].registerEvent('Bridge', self.check_Bridge)
        self.check_test_done()

    def check_UserEvent(self, ami, event):
        if event.get("userevent") != "TestStatus":
            return

        status = event.get('status')
        if status != 'RINGING':
            return

        self.ami[0].registerEvent('Pickup', self.check_Pickup)

        if self.bridgingModel12:
            self.ami[0].registerEvent('BridgeEnter', self.check_BridgeEnter)

        LOGGER.info("Originating Pickup attempt")
        self.ami[0].originate(
            channel = "Local/1002@pickuptest",
            application = "Echo",
        ).addErrback(self.handle_originate_failure)

    def check_Dial(self, ami, event):
        dialstring = event.get('dialstring')
        if dialstring != 'iax_pickup_b/ringing_exten':
            return
        self.firstChannel = event.get('channel')
        LOGGER.info("Detected first channel %s" % self.firstChannel)

    def ami_connect(self, ami):
        running_version = AsteriskVersion()
        post_version = AsteriskVersion("12.0.0")
        if running_version < post_version:
            # Pre-Asterisk 12
            self.ami[0].registerEvent("Dial", self.check_Dial)
        else:
            # Asterisk 12+
            self.bridgingModel12 = True
            self.ami[0].registerEvent("DialBegin", self.check_Dial)
        self.ami[0].registerEvent("UserEvent", self.check_UserEvent)
        LOGGER.info("Originating channel to be picked up")
        self.ami[0].originate(
            channel = "IAX2/iax_pickup_b/1001",
            application = "Echo",
        ).addErrback(self.handle_originate_failure)

    def run(self):
        TestCase.run(self)
        self.create_ami_factory()


def main():
    test = PickupTest()
    test.start_asterisk()
    reactor.run()
    test.stop_asterisk()
    if test.passed != True:
        return 1
    return 0

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

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