# Copyright (C) 2015-2017  The Software Heritage developers
# See the AUTHORS file at the top-level directory of this distribution
# License: GNU Affero General Public License version 3, or any later version
# See top-level LICENSE file for more information

from nose.tools import istest

from .swh_api_testcase import SWHApiTestCase
from swh.web.api.exc import NotFoundExc
from swh.web.api import views


class ApiLookupTestCase(SWHApiTestCase):

    @istest
    def generic_api_lookup_nothing_is_found(self):
        # given
        def test_generic_lookup_fn(sha1, another_unused_arg):
            assert another_unused_arg == 'unused_arg'
            assert sha1 == 'sha1'
            return None

        # when
        with self.assertRaises(NotFoundExc) as cm:
            views._api_lookup(
                test_generic_lookup_fn, 'sha1', 'unused_arg',
                notfound_msg='This will be raised because None is returned.')

            self.assertIn('This will be raised because None is returned.',
                          cm.exception.args[0])

    @istest
    def generic_api_map_are_enriched_and_transformed_to_list(self):
        # given
        def test_generic_lookup_fn_1(criteria0, param0, param1):
            assert criteria0 == 'something'
            return map(lambda x: x + 1, [1, 2, 3])

        # when
        actual_result = views._api_lookup(
            test_generic_lookup_fn_1, 'something', 'some param 0',
            'some param 1',
            notfound_msg=('This is not the error message you are looking for. '
                          'Move along.'),
            enrich_fn=lambda x: x * 2)

        self.assertEqual(actual_result, [4, 6, 8])

    @istest
    def generic_api_list_are_enriched_too(self):
        # given
        def test_generic_lookup_fn_2(crit):
            assert crit == 'something'
            return ['a', 'b', 'c']

        # when
        actual_result = views._api_lookup(
            test_generic_lookup_fn_2, 'something',
            notfound_msg=('Not the error message you are looking for, it is. '
                          'Along, you move!'),
            enrich_fn=lambda x: ''. join(['=', x, '=']))

        self.assertEqual(actual_result, ['=a=', '=b=', '=c='])

    @istest
    def generic_api_generator_are_enriched_and_returned_as_list(self):
        # given
        def test_generic_lookup_fn_3(crit):
            assert crit == 'crit'
            return (i for i in [4, 5, 6])

        # when
        actual_result = views._api_lookup(
            test_generic_lookup_fn_3, 'crit',
            notfound_msg='Move!',
            enrich_fn=lambda x: x - 1)

        self.assertEqual(actual_result, [3, 4, 5])

    @istest
    def generic_api_simple_data_are_enriched_and_returned_too(self):
        # given
        def test_generic_lookup_fn_4(crit):
            assert crit == '123'
            return {'a': 10}

        def test_enrich_data(x):
            x['a'] = x['a'] * 10
            return x

        # when
        actual_result = views._api_lookup(
            test_generic_lookup_fn_4, '123',
            notfound_msg='Nothing to do',
            enrich_fn=test_enrich_data)

        self.assertEqual(actual_result, {'a': 100})

    @istest
    def api_lookup_not_found(self):
        # when
        with self.assertRaises(NotFoundExc) as e:
            views._api_lookup(
                lambda x: None, 'something',
                notfound_msg='this is the error message raised as it is None')

        self.assertEqual(e.exception.args[0],
                         'this is the error message raised as it is None')

    @istest
    def api_lookup_with_result(self):
        # when
        actual_result = views._api_lookup(
            lambda x: x + '!', 'something',
            notfound_msg='this is the error which won\'t be used here')

        self.assertEqual(actual_result, 'something!')

    @istest
    def api_lookup_with_result_as_map(self):
        # when
        actual_result = views._api_lookup(
            lambda x: map(lambda y: y+1, x), [1, 2, 3],
            notfound_msg='this is the error which won\'t be used here')

        self.assertEqual(actual_result, [2, 3, 4])
