# -*- coding: utf-8 -*-

# Copyright (C) 2009-2014 Avencall
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>

import time
from xivo_agid import agid
from xivo_agid.modules import mobile_push_notification

DEFAULT_WAIT_CYCLES = 3
SLEEP_SECONDS = 5

class Contact():

    def __init__(self, user_agent, uri, expiration_time):
        self.user_agent = user_agent
        self.uri = uri
        self.expiration_time = expiration_time

def get_number_of_loops(agi, preferred_device):
    nb_loops = ''
    if preferred_device == 'MobileApp':
        nb_loops = agi.get_variable('XIVO_MAPP_LOOPS_MOBILEAPP')
    elif preferred_device == 'WebAppAndMobileApp':
        nb_loops = agi.get_variable('XIVO_MAPP_LOOPS_WEBAPPANDMOBILEAPP')

    return sanitize_nb_loops(nb_loops)

def sanitize_nb_loops(nb_loops):
    if nb_loops == '':
        return DEFAULT_WAIT_CYCLES
    try:
        if int(nb_loops) <= 0:
            return DEFAULT_WAIT_CYCLES
    except ValueError as ex:
        return DEFAULT_WAIT_CYCLES
    return int(nb_loops)

def find_contact(agi, contactsStr, wanted_ua, expire_before_push):
    if contactsStr == '':
        agi.verbose('No contacts found for this peer')
        return None

    contacts = contactsStr.split(',')
    agi.verbose(f'Searching for new MobileApp contact in contact list {contactsStr}')

    for contact in contacts:
        X_CONTACT_URI = agi.get_variable('PJSIP_CONTACT(%s,uri)' % contact)
        XIVO_MOBILE_PEER_EXPIRE = int(agi.get_variable('PJSIP_CONTACT(%s,expiration_time)' % contact))
        XIVO_TMP_CONTACT_UA = agi.get_variable('PJSIP_CONTACT(%s,user_agent)' % contact)

        edge_ip = agi.get_variable('X_EDGE_IP')

        if edge_ip == '' :
            edge_ip = X_CONTACT_URI.split('@')[1].split(':')[0]
            agi.verbose(f'Setting X_EDGE_IP to {edge_ip}')
            agi.set_variable('X_EDGE_IP', edge_ip)

        if XIVO_TMP_CONTACT_UA == wanted_ua :
            agi.verbose(f'Found contact {contact} for UA {wanted_ua}')
            if XIVO_MOBILE_PEER_EXPIRE > expire_before_push :
                agi.verbose(f'Mobile App contact {contact} has expire time {XIVO_MOBILE_PEER_EXPIRE} > {expire_before_push} (before push): mobile app is re-registered')
                return Contact(XIVO_TMP_CONTACT_UA, X_CONTACT_URI, XIVO_MOBILE_PEER_EXPIRE)
            else :
                agi.verbose(f'Mobile App contact {contact} expire time was not updated')

    return None

def wait_for_wake_up(agi, nb_loops, peer_name, wanted_ua, old_mobile_contact_expire):
    XIVO_PUSH_COUNT = 0

    while(XIVO_PUSH_COUNT != nb_loops):
        agi.verbose(f'Looking if MobileApp re-registered for {peer_name} (cycle #{XIVO_PUSH_COUNT})')
        current_contacts = agi.get_variable('PJSIP_AOR(%s,contact)' % peer_name)
        XIVO_CHECK_PEER_CONTACT_RESULT = find_contact(agi, current_contacts, wanted_ua, old_mobile_contact_expire)
        if  XIVO_CHECK_PEER_CONTACT_RESULT != None :
            return XIVO_CHECK_PEER_CONTACT_RESULT
        XIVO_PUSH_COUNT += 1
        time.sleep(SLEEP_SECONDS)

    return None

def mobile_app_wake_up(agi, cursor, args):
    XIVO_PLAY_MSG = True if args[0] == 'True' else False
    XIVO_MAPP_WAIT_WITH_MUSIC = True if args[1] == 'True' else False
    preferred_device = args[2]
    nb_loops = get_number_of_loops(agi, preferred_device)

    XIVO_SIP_PEER_NAME = agi.get_variable('XIVO_INTERFACE')[6:]
    XIVO_SIP_PEER_CONTACTS = agi.get_variable('PJSIP_AOR(%s,contact)' % XIVO_SIP_PEER_NAME)
    XIVO_SIP_PEER_CONTACT = find_contact(agi, XIVO_SIP_PEER_CONTACTS, 'XiVO PBX', 0)
    XIVO_MOBILE_PEER_EXPIRE_BEFORE_PUSH = XIVO_SIP_PEER_CONTACT.expiration_time if XIVO_SIP_PEER_CONTACT != None else 0
    PJSIP_CALLID = agi.get_variable('CHANNEL(pjsip,call-id)')

    agi.verbose('Calling agi mobile_push_notification')
    mobile_push_notification.mobile_push_notification(agi, None, None, PJSIP_CALLID)

    agi.verbose('Waiting for mobile app to wake up...')
    if XIVO_PLAY_MSG :
        agi.appexec('Playback', 'mobileapp-try-reach-text')
        if XIVO_MAPP_WAIT_WITH_MUSIC:
            agi.set_music('ON')
        else:
            agi.appexec('PlayTones', 'ring')

    XIVO_CHECK_PEER_CONTACT_RESULT = wait_for_wake_up(agi, nb_loops, XIVO_SIP_PEER_NAME, 'XiVO PBX', XIVO_MOBILE_PEER_EXPIRE_BEFORE_PUSH)

    if XIVO_PLAY_MSG :
        if XIVO_MAPP_WAIT_WITH_MUSIC:
            agi.set_music('OFF')
        else :
            agi.appexec('StopPlayTones')

    if XIVO_CHECK_PEER_CONTACT_RESULT == None:
        return f'Mobile App did not wake up after %s seconds, exiting agi ' % (nb_loops * SLEEP_SECONDS)
    else:
        return f'Mobile app contact %s woke up in time' % XIVO_CHECK_PEER_CONTACT_RESULT.user_agent

agid.register(mobile_app_wake_up)
