#!/usr/bin/env python
# vim: sw=3 et:
'''
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

from twisted.internet import reactor

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

from asterisk.asterisk import Asterisk
from asterisk.voicemail import VoiceMailState, VoiceMailTest

logger = logging.getLogger(__name__)

"""
TestState that is the entry point for the VoiceMail application
"""
class StartVoiceMailState(VoiceMailState):

    def __init__(self, controller, voiceMailTest):
        VoiceMailState.__init__(self, controller, voiceMailTest)
        self.login_attempts = 0

    def handle_state_change(self, ami, event):
        state = event['state']
        if state == 'PLAYBACK':
            message = event.get('message')
            if message == 'vm-login' or message == 'vm-incorrect-mailbox':
                self.voice_mail_test.send_dtmf("5555")
                self.voice_mail_test.reset_timeout()
                self.login_attempts += 1
                if (self.login_attempts == 3):
                    logger.info("Failed to login 3 times - setting test result to Pass")
                    self.voice_mail_test.passed = True
            elif message == 'vm-password':
                self.voice_mail_test.send_dtmf("1234")
            elif message == 'vm-goodbye':
                self.voice_mail_test.hangup()
            else:
                self.handle_default_state(event)
        elif state == 'AUTHENTICATED':
            logger.warn("We authenticated with an invalid mailbox - failing the test")
            self.voice_mail_test.passed = False
            self.voice_mail_test.stop_reactor()
        else:
            self.handle_default_state(event)

    def get_state_name(self):
        return "START"

class AuthenticateInvalidMailbox(VoiceMailTest):

    def __init__(self):
        super(AuthenticateInvalidMailbox, self).__init__()
        self.create_asterisk(2)
        self.channel = "sip/ast1/9000"

    def ami_connect(self, ami):
        super(AuthenticateInvalidMailbox, self).ami_connect(ami)

        """ Record which AMI instance we've received and attempt to set up the test controller """
        if (ami.id == 0):
            self.ami_receiver = ami
            ami.registerEvent('UserEvent', self.user_event)
        elif (ami.id == 1):
            self.ami_sender = ami
            self.ast_sender = self.ast[self.ami_sender.id]
            ami.registerEvent('Hangup', self.hangup_event_handler)
        self.create_test_controller()
        if (self.test_state_controller != None):
            startObject = StartVoiceMailState(self.test_state_controller, self)
            self.test_state_controller.change_state(startObject)

        if not (ami.id == 0):
            self.executeTest(ami)

    def hangup_event_handler(self, ami, event):
        logger.debug("Hangup event received; stopping reactor")
        self.stop_reactor()

    def executeTest(self, ami):
        df = ami.originate(self.channel, "voicemailCaller", "wait", 1)
        df.addErrback(self.handle_originate_failure)

    def user_event(self, ami, event):
        if event['userevent'] != 'TestResult':
            return

        """
        Note that in this test, failure to see any UserEvents is a good thing - if we get to a
        UserEvent its because we authenticated something invalid
        """
        self.passed = False
        if event['result'] == 'pass':
            logger.error("Test configuration error - there should be no pass results returned")
        else:
            logger.warn("VMAuthenticate Failure:")
            logger.warn("result: %s" % (event['result'],))
            logger.warn("error: %s" % (event['status'],))

        self.stop_reactor()

    def run(self):
        super(AuthenticateInvalidMailbox, self).run()
        self.passed = True
        self.create_ami_factory(2)


def main():

    test = AuthenticateInvalidMailbox()

    test.start_asterisk()

    reactor.run()

    test.stop_asterisk()

    if not test.passed:
        return 1

    return 0

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