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

# Copyright (C) 2018 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 unittest

from mock import Mock, patch

from xivo_agid import dialplan_variables
from xivo_agid.tools import check_call_fwd, is_call_xferred, get_user_id, get_called_num_for_rights


class TestHelper(unittest.TestCase):

    def setUp(self):
        self._agi = Mock()
        self._cursor = Mock()
        self._args = Mock()

    def test_check_fwd_no(self):
        self._agi.get_variable.side_effect = \
            lambda x: {dialplan_variables.CALLFORWARDED: '',
                       dialplan_variables.FORWARDERNAME: ''}.get(x, '')

        (fwded, fwdtype) = check_call_fwd(self._agi)
        self.assertEqual(fwded, False)
        self.assertEqual(fwdtype, None)

    def test_check_fwd_xivo(self):
        self._agi.get_variable.side_effect = \
            lambda x: {dialplan_variables.CALLFORWARDED: '1',
                       dialplan_variables.FORWARDERNAME: ''}.get(x, '')

        (fwded, fwdtype) = check_call_fwd(self._agi)
        self.assertEqual(fwded, True)
        self.assertEqual(fwdtype, "XIVO")

    def test_check_fwd_sip(self):
        self._agi.get_variable.side_effect = \
            lambda x: {dialplan_variables.CALLFORWARDED: '',
                       dialplan_variables.FORWARDERNAME: 'SIP/efgh-01234567'}.get(x, '')

        (fwded, fwdtype) = check_call_fwd(self._agi)
        self.assertEqual(fwded, True)
        self.assertEqual(fwdtype, "SIP")

    def test_check_fwd_both(self):
        self._agi.get_variable.side_effect = \
            lambda x: {dialplan_variables.CALLFORWARDED: '1',
                       dialplan_variables.FORWARDERNAME: 'SIP/efgh-01234567'}.get(x, '')

        (fwded, fwdtype) = check_call_fwd(self._agi)
        self.assertEqual(fwded, True)
        self.assertEqual(fwdtype, "XIVO")

    def test_is_call_xferred_no(self):
        self._agi.get_variable.side_effect = \
            lambda x: {dialplan_variables.SIPTRANSFER: '',
                       dialplan_variables.BLINDTRANSFER: '',
                       dialplan_variables.ATTENDEDTRANSFER: ''}.get(x, '')

        res = is_call_xferred(self._agi)
        self.assertEqual(res, False)

    def test_is_call_xferred_direct(self):
        self._agi.get_variable.side_effect = \
            lambda x: {dialplan_variables.SIPTRANSFER: 'yes',
                       dialplan_variables.BLINDTRANSFER: 'SIP/abcd-0000004a',
                       dialplan_variables.ATTENDEDTRANSFER: ''}.get(x, '')

        res = is_call_xferred(self._agi)
        self.assertEqual(res, True)

    def test_is_call_xferred_attended(self):
        self._agi.get_variable.side_effect = \
            lambda x: {dialplan_variables.SIPTRANSFER: '',
                       dialplan_variables.BLINDTRANSFER: '',
                       dialplan_variables.ATTENDEDTRANSFER: 'SIP/efgh-0000004a'}.get(x, '')

        res = is_call_xferred(self._agi)
        self.assertEqual(res, True)

    @patch('xivo_agid.tools.check_call_fwd')
    def test_get_user_id_internal_call_not_fwded(self, mock_check_call_fwd):
        # User U1 calls user U2

        U1 = {'USERID': '11', 'INTERFACE': 'SIP/abcd'}
        U2 = {'USERID': '22', 'INTERFACE': 'SIP/efgh'}

        self._agi.get_variable.side_effect = \
            lambda x: {dialplan_variables.USERID: U1['USERID'],
                       }.get(x, '')
        mock_check_call_fwd.return_value = (False, None)

        self.assertEqual(get_user_id(self._agi), U1['USERID'])

    @patch('xivo_agid.tools.check_call_fwd')
    def test_get_user_id_internal_call_fwded(self, mock_check_call_fwd):
        # User U1 calls user U2 fwded to U3
        # U2's userid should be returned

        U1 = {'USERID': '11', 'INTERFACE': 'SIP/abcd'}
        U2 = {'USERID': '22', 'INTERFACE': 'SIP/efgh'}
        U3 = {'USERID': '33', 'INTERFACE': 'SIP/ijkl'}

        self._agi.get_variable.side_effect = \
            lambda x: {dialplan_variables.USERID: U1['USERID'],
                       dialplan_variables.FWD_REFERER: 'user:%s' % U2['USERID'],
                       }.get(x, '')
        mock_check_call_fwd.return_value = (True, "XIVO")

        self.assertEqual(get_user_id(self._agi), U2['USERID'])

    @patch('xivo_agid.tools.check_call_fwd')
    def test_get_user_id_internal_call_fwded_not_from_user(self, mock_check_call_fwd):
        # User U1 calls <something> (e.g. a queue) fwded to U3
        # empty userid should be returned

        U1 = {'USERID': '11', 'INTERFACE': 'SIP/abcd'}
        U3 = {'USERID': '33', 'INTERFACE': 'SIP/ijkl'}

        self._agi.get_variable.side_effect = \
            lambda x: {dialplan_variables.USERID: U1['USERID'],
                       dialplan_variables.FWD_REFERER: 'notuser:2'
                       }.get(x, '')
        mock_check_call_fwd.return_value = (True, "XIVO")

        self.assertEqual(get_user_id(self._agi), '')

    @patch('xivo_agid.tools.check_call_fwd')
    def test_get_user_id_internal_call_fwded_referer_empty(self, mock_check_call_fwd):
        # User U1 calls user U2 fwded to U3
        # but referer is empty (dialplan bug)
        # empty userid should be return (it'll bypass call permission in this case)

        U1 = {'USERID': '11', 'INTERFACE': 'SIP/abcd'}

        self._agi.get_variable.side_effect = \
            lambda x: {dialplan_variables.USERID: U1['USERID'],
                       dialplan_variables.FWD_REFERER: 'user:'
                       }.get(x, '')
        mock_check_call_fwd.return_value = (True, "XIVO")

        self.assertEqual(get_user_id(self._agi), '')

    @patch('xivo_agid.tools.check_call_fwd')
    def test_get_user_id_internal_call_fwded_referer_badformat(self, mock_check_call_fwd):
        # User U1 calls user U2 fwded to U3
        # but referer is badly formatted (dialplan bug)
        # empty userid should be return (it'll bypass call permission in this case)

        U1 = {'USERID': '11', 'INTERFACE': 'SIP/abcd'}

        self._agi.get_variable.side_effect = \
            lambda x: {dialplan_variables.USERID: U1['USERID'],
                       dialplan_variables.FWD_REFERER: 'user'
                       }.get(x, '')
        mock_check_call_fwd.return_value = (True, "XIVO")

        self.assertEqual(get_user_id(self._agi), '')

    @patch('xivo_agid.tools.check_call_fwd')
    @patch('xivo_dao.user_line_dao.get_id_from_channel')
    def test_get_user_id_internal_call_fwded_by_phone(self, mock_get_id_from_channel, mock_check_call_fwd):
        # User U1 calls user U2 fwded to <some number>
        # with fwd set on phone set (not with xivo feature)
        # U2's userid should be returned

        U1 = {'USERID': '11', 'INTERFACE': 'SIP/abcd'}
        U2 = {'USERID': '22', 'INTERFACE': 'SIP/efgh'}
        U3 = {'USERID': '33', 'INTERFACE': 'SIP/ijkl'}

        self._agi.get_variable.side_effect = \
            lambda x: {dialplan_variables.USERID: U1['USERID'],
                       dialplan_variables.FWD_REFERER: '',
                       dialplan_variables.FORWARDERNAME: '%s-0000987f' % U2['INTERFACE']
                       }.get(x, '')
        mock_check_call_fwd.return_value = (True, "SIP")
        mock_get_id_from_channel.return_value = U2['USERID']

        self.assertEqual(get_user_id(self._agi), U2['USERID'])
        mock_get_id_from_channel.assert_called_once_with('%s-0000987f' % U2['INTERFACE'])

    @patch('xivo_agid.tools.check_call_fwd')
    def test_get_called_num_for_rights_nofwd(self, mock_check_call_fwd):
        # User U1 calls user U2

        U2_NUMBER = '2222'
        FWDTYPE = None

        self._agi.get_variable.side_effect = \
            lambda x: {dialplan_variables.DESTINATION_NUMBER: U2_NUMBER,
                       }.get(x, '')
        mock_check_call_fwd.return_value = (False, FWDTYPE)

        self.assertEqual(get_called_num_for_rights(self._agi), U2_NUMBER)

    @patch('xivo_agid.tools.check_call_fwd')
    def test_get_called_num_for_rights_extension_fwd(self, mock_check_call_fwd):
        # User U1 calls user U2 fwded (*21) U3
        U2_NUMBER = '2222'
        U3_NUMBER = '3333'
        FWDTYPE = "XIVO"

        self._agi.get_variable.side_effect = \
            lambda x: {dialplan_variables.DESTINATION_NUMBER: U2_NUMBER,
                       'XIVO_FWD_ACTION': 'extension',
                       'XIVO_FWD_ACTIONARG1': U3_NUMBER
                       }.get(x, '')
        mock_check_call_fwd.return_value = (True, FWDTYPE)

        self.assertEqual(get_called_num_for_rights(self._agi), U3_NUMBER)

    @patch('xivo_agid.tools.check_call_fwd')
    @patch('xivo_dao.user_line_dao.get_main_exten_by_user_id')
    def test_get_called_num_for_rights_xivo_redir(self, mock_main_exten_by_user_id, mock_check_call_fwd):
        # User U1 calls user U2 redir on noanswer U3
        U2_NUMBER = '2222'
        U3_NUMBER = '3333'
        U3_USERID = 33
        FWDTYPE = "XIVO"

        self._agi.get_variable.side_effect = \
            lambda x: {dialplan_variables.DESTINATION_NUMBER: U2_NUMBER,
                       'XIVO_FWD_ACTION': 'user',
                       'XIVO_FWD_ACTIONARG1': U3_USERID
                       }.get(x, '')
        mock_check_call_fwd.return_value = (True, FWDTYPE)
        mock_main_exten_by_user_id.return_value = U3_NUMBER

        self.assertEqual(get_called_num_for_rights(self._agi), U3_NUMBER)

    @patch('xivo_agid.tools.check_call_fwd')
    def test_get_called_num_for_rights_sip_fwd(self, mock_check_call_fwd):
        # User U1 calls user U2 fwded (SIP) U3
        U2_NUMBER = '2222'
        U3_NUMBER = '3333'
        FWDTYPE = "SIP"

        self._agi.get_variable.side_effect = \
            lambda x: {dialplan_variables.DESTINATION_NUMBER: U3_NUMBER,
                       }.get(x, '')
        mock_check_call_fwd.return_value = (True, FWDTYPE)

        self.assertEqual(get_called_num_for_rights(self._agi), U3_NUMBER)
