#!/usr/bin/env python
'''
Copyright (C) 2013-2014, Digium, Inc.
Jonathan Rose <jrose@digium.com>
Joshua Colp <jcolp@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
import re

from twisted.internet import reactor

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

LOGGER = logging.getLogger(__name__)

class CallPickupTest(TestCase):

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

        self.pickeeChannel = re.compile("Local/dial_faker@pickuptest-")
        self.pickerChannel = re.compile("PJSIP/sip_receive-")
        self.targetChannel = re.compile("PJSIP/faker-")

        self.bridge = None

        self.bridgeComplete = False
        self.pickupComplete = False

        self.pickerJoined = False
        self.pickeeJoined = False

        self.connectionsEstablished = 0

        self.create_asterisk(count=2)

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

    def check_bridge_enter(self, ami, event):
        channel = event.get('channel')
        bridge = event.get('bridgeuniqueid')

        if not self.bridge:
            self.bridge = bridge
        elif self.bridge != bridge:
            LOGGER.error("The bridge ID mismatch - got %s - expected %s - FAIL" % (bridge, self.bridge))
            self.set_passed(False)
            self.stop_reactor()

        if self.pickerChannel.match(channel):
            self.pickerJoined = True
        elif self.pickeeChannel.match(channel):
            self.pickeeJoined = True
        else:
            LOGGER.error("Unexpected Channel %s joined the bridge - FAIL" % channel)
            self.set_passed(False)
            self.stop_reactor()

        if self.pickerJoined and self.pickeeJoined:
            if self.pickupComplete:
                self.set_passed(True)
                self.ami[0].hangup(channel).addCallback(self.hangup)
            else:
                self.bridgeComplete = True

    def check_pickup(self, ami, event):
        picker = event.get("channel")
        target = event.get("targetchannel")

        if self.pickerChannel.match(picker) and self.targetChannel.match(target):
            if self.bridgeComplete:
                self.set_passed(True)
                self.ami[0].hangup(picker).addCallback(self.hangup)
            else:
                self.pickupComplete = True

    def check_dial(self, ami, event):
        dialstring = event.get('dialstring')
        if dialstring != 'faker':
            return

        self.ami[0].registerEvent('Pickup', self.check_pickup)
        self.ami[0].registerEvent('BridgeEnter', self.check_bridge_enter)

        LOGGER.info("Originating Pickup attempt")

        self.ami[1].originate(
            channel="Local/test_out@pickuptest",
            exten="pickup_exten",
            context="pickuptest",
            priority="1"
        ).addErrback(self.handle_originate_failure)

    def ami_connect(self, ami):
        self.connectionsEstablished += 1

        if self.connectionsEstablished != 2:
            return

        self.ami[0].registerEvent("DialBegin", self.check_dial)

        LOGGER.info("Originating channel to be picked up")
        self.ami[0].originate(
            channel="Local/dial_faker@pickuptest",
            exten="test_fuzz",
            context="pickuptest",
            priority=1
        ).addErrback(self.handle_originate_failure)

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

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

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

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