# -*- 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, call
import os

from xivo_agid import dialplan_variables
from xivo_agid.modules.xds_routing import _get_mds_address, _get_mds_from_peer_secret, \
    _xds_routing


class TestXDSRouting(unittest.TestCase):

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

    def side_effect_address(arg, exten_context, cursor):
        values = {'1001': ('mds1', '10.0.1.10'),
                  '1002': ('mds2', '10.0.1.20'),
                  '1003': ('mds1', '10.0.1.10'),
                  '1004': ('mds1', '10.0.1.10')}
        return values[arg]

    def side_effect_secret(arg, cursor):
        values = {'mds1': 'secret'}
        return values[arg]

    @patch("psycopg2.connect")
    def test_get_mds_address(self, mock_connect):
        expected = {"linefeatures.configregistrar": "mds2", "all_mediaserver.voip_ip": "10.0.1.10"}
        context = 'default'

        mock_con = mock_connect.return_value
        mock_cursor = mock_con.cursor.return_value
        mock_cursor.fetchone.return_value = expected

        self.assertEqual(_get_mds_address('1001', context, mock_cursor), ('mds2', '10.0.1.10'))

    @patch("psycopg2.connect")
    def test_get_mds_from_peer_secret(self, mock_connect):
        expected = {"usersip.secret": "secret"}

        mock_con = mock_connect.return_value
        mock_cursor = mock_con.cursor.return_value
        mock_cursor.fetchone.return_value = expected

        self.assertEqual(_get_mds_from_peer_secret('mds1', mock_cursor), 'secret')

    @patch.dict(os.environ, {'MDS_NAME': 'mds1'})
    @patch("xivo_agid.modules.xds_routing._get_mds_address", side_effect=side_effect_address)
    @patch("xivo_agid.modules.xds_routing._get_mds_from_peer_secret", side_effect=side_effect_secret)
    def test_xds_routing_on_different_mds(self, mock_get_mds_from_peer_secret, mock_get_mds_address):
        expected = [call(dialplan_variables.XDS_FROMPEER, 'mds1'),
                    call(dialplan_variables.XDS_CALLEDNUMBER, '1002'),
                    call(dialplan_variables.XDS_FROMPEERSECRET, 'secret'),
                    call(dialplan_variables.XDS_DST_IP, '10.0.1.20')]

        self._agi.get_variable.side_effect = \
            lambda x: {dialplan_variables.EXTEN: '1002',
                       dialplan_variables.DESTINATION_NUMBER: '1002',
                       dialplan_variables.SRCNUM: '1001',
                       dialplan_variables.BASE_EXTEN: '1002',
                       dialplan_variables.SIPDOMAIN: '10.0.1.10',
                       dialplan_variables.BASE_CONTEXT: 'default'}.get(x, '')

        _xds_routing(self._agi, self._cursor, self._args)

        self.assertEqual(self._agi.set_variable.call_args_list, expected)
        mock_get_mds_from_peer_secret.assert_called_with('mds1', self._cursor)
        mock_get_mds_address.assert_called_with('1002', 'default', self._cursor)

    @patch.dict(os.environ, {'MDS_NAME': 'mds1'})
    @patch("xivo_agid.modules.xds_routing._get_mds_address", side_effect=side_effect_address)
    @patch("xivo_agid.modules.xds_routing._get_mds_from_peer_secret", side_effect=side_effect_secret)
    def test_xds_routing_on_different_mds_different_context(self, mock_get_mds_from_peer_secret, mock_get_mds_address):
        expected = [call(dialplan_variables.XDS_FROMPEER, 'mds1'),
                    call(dialplan_variables.XDS_CALLEDNUMBER, '1002'),
                    call(dialplan_variables.XDS_FROMPEERSECRET, 'secret'),
                    call(dialplan_variables.XDS_DST_IP, '10.0.1.20')]

        self._agi.get_variable.side_effect = \
            lambda x: {dialplan_variables.EXTEN: '1002',
                       dialplan_variables.DESTINATION_NUMBER: '1002',
                       dialplan_variables.SRCNUM: '1001',
                       dialplan_variables.BASE_EXTEN: '1002',
                       dialplan_variables.SIPDOMAIN: '10.0.1.10',
                       dialplan_variables.XDS_CONTEXT: 'site-main'}.get(x, '')

        _xds_routing(self._agi, self._cursor, self._args)

        self.assertEqual(self._agi.set_variable.call_args_list, expected)
        mock_get_mds_from_peer_secret.assert_called_with('mds1', self._cursor)
        mock_get_mds_address.assert_called_with('1002', 'site-main', self._cursor)
