#!/usr/bin/env python
'''
Copyright (C) 2011, Digium, Inc.
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 logging

sys.path.append("lib/python")

from asterisk.asterisk import Asterisk
from asterisk.test_case import TestCase
from asterisk.sipp import SIPpScenario
from twisted.internet import reactor
from asterisk.version import AsteriskVersion

LOGGER = logging.getLogger(__name__)
INJECT_FILE_BRIDGE = "inject_bridge.csv"

class SIPHold(TestCase):
    def __init__(self):
        TestCase.__init__(self)
        self.create_asterisk()

        running_version = AsteriskVersion()

        if (running_version < AsteriskVersion("12.0.0")):
            #Pre-12
            self.asterisk12Events = False
        else:
            self.asterisk12Events = True

        self.sipp_phone_a_scenarios = [
            {'scenario':'phone_A.xml','-i':'127.0.0.2','-p':'5060','-inf':INJECT_FILE_BRIDGE},
            {'scenario':'phone_A_IP_restrict.xml','-i':'127.0.0.2','-p':'5060','-inf':INJECT_FILE_BRIDGE},
            {'scenario':'phone_A.xml','-i':'127.0.0.2','-p':'5060','-inf':INJECT_FILE_BRIDGE},
            ]
        self.sipp_phone_b_scenarios = [
            {'scenario':'phone_B_media_restrict.xml','-i':'127.0.0.3','-p':'5060','-inf':INJECT_FILE_BRIDGE},
            {'scenario':'phone_B_IP_restrict.xml','-i':'127.0.0.3','-p':'5060','-inf':INJECT_FILE_BRIDGE},
            {'scenario':'phone_B_IP_media_restrict.xml','-i':'127.0.0.3','-p':'5060','-inf':INJECT_FILE_BRIDGE},
            ]

        self.passed = True
        self.moh_start_events = 0
        self.moh_stop_events = 0
        self.user_events = 0
        self.__test_counter = 0

    def ami_connect(self, ami):
        TestCase.ami_connect(self, ami)
        ami.registerEvent('UserEvent', self.user_event_handler)

        if self.asterisk12Events:
            ami.registerEvent('MusicOnHoldStart', self.moh_start_event_handler)
            ami.registerEvent('MusicOnHoldStop', self.moh_stop_event_handler)
        else:
            ami.registerEvent('MusicOnHold', self.moh_event_handler)

        LOGGER.info("Starting SIP scenario")
        self.execute_scenarios()

    def execute_scenarios(self):
        def __check_scenario_a(result):
            self.__a_finished = True
            return result

        def __check_scenario_b(result):
            self.__b_finished = True
            return result

        def __execute_next_scenario(result):
            if self.__a_finished and self.__b_finished:
                self.__test_counter += 1
                self.reset_timeout()
                self.execute_scenarios()
            return result

        if self.__test_counter == len(self.sipp_phone_a_scenarios):
            LOGGER.info("All scenarios executed")
            return

        sipp_a = SIPpScenario(self.test_name, self.sipp_phone_a_scenarios[self.__test_counter])
        sipp_b = SIPpScenario(self.test_name, self.sipp_phone_b_scenarios[self.__test_counter])

        # Start up the listener first - Phone A calls Phone B
        self.__a_finished = False
        self.__b_finished = False
        db = sipp_b.run(self)
        da = sipp_a.run(self)

        da.addCallback(__check_scenario_a)
        da.addCallback(__execute_next_scenario)
        db.addCallback(__check_scenario_b)
        db.addCallback(__execute_next_scenario)

    def user_event_handler(self, ami, event):
        self.user_events += 1
        if (self.user_events == len(self.sipp_phone_a_scenarios)):
            LOGGER.info("All user events received; stopping reactor")
            self.stop_reactor()

    def moh_start_event_handler(self, ami, event):
        LOGGER.debug("Received MOH start event")
        self.moh_start_events += 1

    def moh_stop_event_handler(self, ami, event):
        LOGGER.debug("Received MOH stop event")
        self.moh_stop_events += 1

    def moh_event_handler(self, ami, event):
        if event['state'] == "Start":
            LOGGER.debug("Received MOH start event")
            self.moh_start_events += 1
        elif event['state'] == "Stop":
            LOGGER.debug("Received MOH stop event")
            self.moh_stop_events += 1

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


def main():
    test = SIPHold()
    test.start_asterisk()
    reactor.run()
    test.stop_asterisk()

    if (test.moh_start_events != len(test.sipp_phone_a_scenarios)):
        LOGGER.error("Failed to receive %d MOH start events (received %d)" % (len(test.sipp_phone_a_scenarios), test.moh_start_events))
        test.passed = False
    if (test.moh_stop_events != len(test.sipp_phone_a_scenarios)):
        LOGGER.error("Failed to receive %d MOH stop events (received %d)" % (len(test.sipp_phone_a_scenarios), test.moh_stop_events))
        test.passed = False
    if (test.user_events != len(test.sipp_phone_a_scenarios)):
        LOGGER.error("Failed to receive %d user test events (received %d)" % (len(test.sipp_phone_a_scenarios), test.user_events))
        test.passed = False

    if test.passed:
        return 0
    else:
        return 1


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


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