# -*- coding: utf-8 -*-
#
# Copyright (C) 2015 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 hamcrest import assert_that
from hamcrest import described_as
from hamcrest import equal_to

from xivo_dird.helpers import RaiseStopper
from xivo_dird.helpers import remove_diacritics, tokenize, normalize_term, terms_match_array, remove_empty_values


def _ok(ignored, returned):
    return returned


def _throwing():
    raise AssertionError('Should not happen')


class TestNoThrowExecute(unittest.TestCase):

    def test_that_the_result_is_returned(self):
        result = RaiseStopper(return_on_raise=None).execute(_ok, 1, 2)

        assert_that(result, equal_to(2))

    def test_that_exceptions_are_consumed(self):
        RaiseStopper(return_on_raise=None).execute(_throwing)

    def test_that_the_default_return_value_is_used_for_exceptions(self):
        result = RaiseStopper(return_on_raise=['one', 'two']).execute(_throwing)

        assert_that(result, equal_to(['one', 'two']))

    def test_remove_diacritics(self):
        assert_that(remove_diacritics(u'éàçùêëôö'), equal_to(u'eacueeoo'))

    def test_remove_diacritics_empty_string(self):
        assert_that(remove_diacritics(None), equal_to(u''))

    def test_remove_diacritics_convert_unicode(self):
        assert_that(remove_diacritics('eacueeoo'), equal_to(u'eacueeoo'))

    def test_normalize_should_remove_diacritics_and_lowercase(self):
        assert_that(normalize_term(u'EAéàçùêëôöUI'), equal_to(u'eaeacueeooui'))

    def test_tokenize_terms(self):
        test_cases = [
            {'search': 'AbCdE', 'expected_terms': [u'abcde'], 'description': 'lowercase characters'},
            {'search': u'éàçùêëôö', 'expected_terms': [u'eacueeoo'], 'description': 'remove diacritics'},
            {'search': 'Jean Pierre', 'expected_terms': [u'jean', u'pierre'], 'description': 'split using space'},
            {'search': 'Jean-Pierre', 'expected_terms': [u'jean', u'pierre'], 'description': 'split using dash'},
            {'search': 'Jean,Pierre', 'expected_terms': [u'jean', u'pierre'], 'description': 'split using comma'},
            {'search': 'Jean-Pierre Thomasset', 'expected_terms': [u'jean', u'pierre', u'thomasset'],
             'description': 'split using space and dash'},
            {'search': 'Jean,', 'expected_terms': [u'jean'], 'description': 'remove empty string'},
        ]
        for t in test_cases:
            result = tokenize(t['search'])
            assert_that(result,
                        described_as('tokenize_terms should ' + t['description'] + ': ' + t['search'] + ' to ' + str(
                            t['expected_terms']), equal_to(t['expected_terms'])))

    def test_terms_match_array(self):
        test_cases = [
            {'terms': [u'jean'], 'input': [u'Jean-Pierre', u'Thomasset', u'Avencall'], 'match': True},
            {'terms': [u'jean', u'pierre'], 'input': [u'Jean-Pierre', u'Thomasset', u'Avencall'], 'match': True},
            {'terms': [u'jean', u'thomasset'], 'input': [u'Jean-Pierre', u'Thomasset', u'Avencall'], 'match': True},
            {'terms': [u'michel', u'thomasset'], 'input': [u'Jean-Pierre', u'Thomasset', u'Avencall'], 'match': False},
            {'terms': [u'pere', u'noel'], 'input': [u'Père', u'Noël', u'Christmas Inc'], 'match': True},
        ]

        for t in test_cases:
            result = terms_match_array(t['terms'], t['input'])
            assert_that(result,
                        described_as(
                            str(t['terms']) + ' should ' + ('NOT MATCH ' if not t['match'] else 'match ') + str(
                                t['input']),
                            equal_to(t['match'])))

    def test_remove_empty_values(self):
        input = {'empty': None, 'full': 'full'}
        expected = ['full']
        assert_that(list(remove_empty_values(input).keys()), equal_to(expected))
