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

# Copyright (C) 2011-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 io import StringIO

from mock import Mock, patch

from xivo_confgen.generators.extensionsconf import ExtensionsConf
from xivo_confgen.hints.generator import HintGenerator


class ExtensionsConfBuilder(object):

    def __init__(self):
        self.contextsconf = 'context.conf'
        self.hint_generator = Mock(HintGenerator)

    def build(self):
        extensionsconf = ExtensionsConf(self.contextsconf, self.hint_generator)
        return extensionsconf


class TestExtensionsConf(unittest.TestCase):

    def test_generate_dialplan_from_template(self):
        extensionsconf = (ExtensionsConfBuilder()
                          .build())

        output = StringIO()
        template = ["%%EXTEN%%,%%PRIORITY%%,Set('XIVO_BASE_CONTEXT': ${CONTEXT})"]
        exten = {'exten': '*98', 'priority': 1}

        extensionsconf.gen_dialplan_from_template(template, exten, output)

        self.assertEqual(output.getvalue(), "exten = *98,1,Set('XIVO_BASE_CONTEXT': ${CONTEXT})\n\n")

    def test_bsfilter_build_extens(self):
        extensionsconf = (ExtensionsConfBuilder()
                          .build())

        bs1 = {'bsfilter': 'boss',
               'exten': 1001,
               'number': 1000}
        query_result = [bs1]

        result = extensionsconf._build_sorted_bsfilter(query_result)

        expected = set([(1000, 1001)])

        self.assertEqual(result, expected)

    def test_bsfilter_build_extend_no_double(self):
        extensionsconf = (ExtensionsConfBuilder()
                          .build())

        bs1 = {'bsfilter': 'boss',
               'exten': 1001,
               'number': 1000}
        bs2 = {'bsfilter': 'secretary',
               'exten': 1000,
               'number': 1001}
        query_result = [bs1, bs2]

        result = extensionsconf._build_sorted_bsfilter(query_result)

        expected = set([(1000, 1001)])

        self.assertEqual(result, expected)

    def test_bsfilter_build_extend_no_two_secretaries(self):
        extensionsconf = (ExtensionsConfBuilder()
                          .build())

        bs1 = {'bsfilter': 'boss',
               'exten': 1001,
               'number': 1000}
        bs2 = {'bsfilter': 'secretary',
               'exten': 1000,
               'number': 1001}
        bs3 = {'bsfilter': 'boss',
               'exten': 1002,
               'number': 1000}
        bs4 = {'bsfilter': 'secretary',
               'exten': 1000,
               'number': 1002}
        query_result = [bs1, bs2, bs3, bs4]

        result = extensionsconf._build_sorted_bsfilter(query_result)

        expected = set([(1000, 1001), (1000, 1002)])

        self.assertEqual(result, expected)

    def test_generate_hints(self):
        extensionsconf = (ExtensionsConfBuilder()
                          .build())

        output = StringIO()
        hints = [
            'exten = 1000,hint,SIP/abcdef',
            'exten = 4000,hint,meetme:4000',
            'exten = *7351***223*1234,hint,Custom:*7351***223*1234',
        ]

        extensionsconf.hint_generator.generate.return_value = hints

        extensionsconf._generate_hints('context', output, extensionsconf.systemname)

        extensionsconf.hint_generator.generate.assert_called_once_with('context', 'default')
        for hint in hints:
            self.assertTrue(hint in output.getvalue())

    def test_generate_hints_for_mds(self):
        extensionsconf = (ExtensionsConfBuilder()
                          .build())
        extensionsconf.systemname = "mds1"

        output = StringIO()
        hints = [
            'exten = 1001,hint,SIP/fedcba',
            'exten = *7351***223*1234,hint,Custom:*7351***223*1234',
        ]

        extensionsconf.hint_generator.generate.return_value = hints

        extensionsconf._generate_hints('context', output, extensionsconf.systemname)

        extensionsconf.hint_generator.generate.assert_called_once_with('context', 'mds1')
        for hint in hints:
            self.assertTrue(hint in output.getvalue())

    def test_generate_exten_action_without_mds(self):
        extensionsconf = (ExtensionsConfBuilder()
                          .build())

        context = 'default'

        extens = [{'exten_value': '3000', 'exten_type': 'queue', 'exten_typeval': '33'},
                  {'exten_value': '4000', 'exten_type': 'meetme', 'exten_typeval': '44'}, ]

        for exten in extens:
            expected_action = 'GoSub(%s,s,1(%s,))' % (exten['exten_type'], exten['exten_typeval'])

            result = extensionsconf._generate_exten_action(exten['exten_value'], exten['exten_type'],
                                                           exten['exten_typeval'], context)

            self.assertEqual(result, expected_action)

    def test_generate_exten_action_with_mds(self):
        context = 'default'

        extensionsconf = (ExtensionsConfBuilder()
                          .build())
        extensionsconf.systemname = "mds1"

        extens = [{'exten_value': '3000', 'exten_type': 'queue', 'exten_typeval': '33', 'mediaserver': 'default'},
                  {'exten_value': '4000', 'exten_type': 'meetme', 'exten_typeval': '44', 'mediaserver': 'default'}, ]

        for exten in extens:
            expected_action = 'GoSub(xds-to-mds,%s,1(default,default))' % (exten['exten_value'],)

            result = extensionsconf._generate_exten_action(exten['exten_value'], exten['exten_type'],
                                                           exten['exten_typeval'], context, exten['mediaserver'])

            self.assertEqual(result, expected_action)

    @patch('xivo_dao.asterisk_conf_dao.is_extension_on_current_mds')
    def test_generate_exten_action_user_with_mds(self, mock_is_extension_on_current_mds):
        context = 'default'

        mds = {'peername': 'mds1',
               'peersecret': 'xds',
               'xmainip': '10.32.5.2'}
        extensionsconf = (ExtensionsConfBuilder().build())

        extens = [{'exten_value': '1000', 'exten_type': 'user', 'exten_typeval': '5'},
                  {'exten_value': '2000', 'exten_type': 'user', 'exten_typeval': '6'}, ]

        mock_is_extension_on_current_mds.return_value = True

        for exten in extens:
            expected_action = 'GoSub(%s,s,1(%s,))' % (exten['exten_type'], exten['exten_typeval'])

            result = extensionsconf._generate_exten_action(exten['exten_value'], exten['exten_type'],
                                                           exten['exten_typeval'], context)

            self.assertEqual(result, expected_action)

    def test_generate_exten_action_user_with_remote_mds(self):
        context = 'site-mds'

        extensionsconf = (ExtensionsConfBuilder()
                          .build())
        extensionsconf.systemname = "default"
        exten = {'exten_value': '1000', 'exten_type': 'user', 'exten_typeval': '5', 'mediaserver': 'mds1'}

        expected_action = 'GoSub(xds-to-mds,1000,1(mds1,site-mds))'
        result = extensionsconf._generate_exten_action(exten['exten_value'], exten['exten_type'],
                                                       exten['exten_typeval'], context, exten['mediaserver'])

        self.assertEqual(result, expected_action)

    def test_generate_exten_action_user_with_remote_main(self):
        context = 'site-mds'

        extensionsconf = (ExtensionsConfBuilder()
                          .build())
        extensionsconf.systemname = "mds1"
        exten = {'exten_value': '1000', 'exten_type': 'user', 'exten_typeval': '5', 'mediaserver': 'default'}

        expected_action = 'GoSub(xds-to-mds,1000,1(default,site-mds))'
        result = extensionsconf._generate_exten_action(exten['exten_value'], exten['exten_type'],
                                                       exten['exten_typeval'], context, exten['mediaserver'])

        self.assertEqual(result, expected_action)

    @patch('xivo_dao.asterisk_conf_dao.is_extension_on_current_mds')
    def test_generate_exten_action_user_with_local_main(self, mock_is_extension_on_current_mds):
        context = 'default'

        extensionsconf = (ExtensionsConfBuilder().build())

        exten = {'exten_value': '1000', 'exten_type': 'user', 'exten_typeval': '5'}

        mock_is_extension_on_current_mds.return_value = True

        expected_action = 'GoSub(user,s,1(5,))'
        result = extensionsconf._generate_exten_action(exten['exten_value'], exten['exten_type'],
                                                       exten['exten_typeval'], context)

        self.assertEqual(result, expected_action)

    @patch('xivo_dao.asterisk_conf_dao.is_extension_on_current_mds')
    def test_generate_exten_action_group_with_mds(self, mock_is_extension_on_current_mds):
        context = 'default'

        mds = {'peername': 'mds1',
               'peersecret': 'xds',
               'xmainip': '10.32.5.2'}
        extensionsconf = (ExtensionsConfBuilder().build())

        extens = [{'exten_value': '1000', 'exten_type': 'group', 'exten_typeval': '5'},
                  {'exten_value': '2000', 'exten_type': 'group', 'exten_typeval': '6'}, ]

        mock_is_extension_on_current_mds.return_value = True

        for exten in extens:
            expected_action = 'GoSub(%s,s,1(%s,))' % (exten['exten_type'], exten['exten_typeval'])

            result = extensionsconf._generate_exten_action(exten['exten_value'], exten['exten_type'],
                                                           exten['exten_typeval'], context)

            self.assertEqual(result, expected_action)

    def test_generate_exten_action_group_with_remote_mds(self):
        context = 'site-mds'

        extensionsconf = (ExtensionsConfBuilder()
                          .build())
        extensionsconf.systemname = 'default'

        exten = {'exten_value': '1000', 'exten_type': 'group', 'exten_typeval': '5', 'mediaserver': 'mds1'}

        expected_action = 'GoSub(xds-to-mds,1000,1(mds1,site-mds))'
        result = extensionsconf._generate_exten_action(exten['exten_value'], exten['exten_type'],
                                                       exten['exten_typeval'], context, exten['mediaserver'])

        self.assertEqual(result, expected_action)

    def test_generate_exten_action_group_with_remote_main(self):
        context = 'site-main'
        extensionsconf = (ExtensionsConfBuilder()
                          .build())
        extensionsconf.systemname = 'mds1'

        exten = {'exten_value': '1000', 'exten_type': 'group', 'exten_typeval': '5', 'mediaserver': 'default'}

        expected_action = 'GoSub(xds-to-mds,1000,1(default,site-main))'
        result = extensionsconf._generate_exten_action(exten['exten_value'], exten['exten_type'],
                                                       exten['exten_typeval'], context, exten['mediaserver'])

        self.assertEqual(result, expected_action)

    def test_generate_exten_action_group_with_local_main(self):
        context = 'default'
        extensionsconf = (ExtensionsConfBuilder().build())
        extensionsconf.systemname = 'default'

        exten = {'exten_value': '1000', 'exten_type': 'group', 'exten_typeval': '5', 'mediaserver': 'default'}

        expected_action = 'GoSub(group,s,1(5,))'
        result = extensionsconf._generate_exten_action(exten['exten_value'], exten['exten_type'],
                                                       exten['exten_typeval'], context, exten['mediaserver'])

        self.assertEqual(result, expected_action)
