"""This module contains the test cases for the ``templatetags`` module"""

from django.test import RequestFactory
from django.test import TestCase
from django.views.generic.list import ListView


class TemplateTagsTestCase(TestCase):
    """TestCase for templatetags."""

    class DummyListView(ListView):
        """Dummy ``ListView`` based class to test pagination."""

        template_name = 'test/test_pagination.html'
        paginate_by = 4

        def get_queryset(self):
            """Returns a simple list of dict"""

            # use 19 to have all page with 4 entries except the last one
            # which should have 3 entries
            return [{'name': '%s' % i} for i in range(19)]

    def test_pagination_links(self):
        """Test the `{% pagination %}` templatetag without tied form, using links

        We test with and without existing querystring:
        - a big page without pagination
        - the first page
        - a page in the middle
        - the last page

        Each time we check for
        - that the link(s) are present
        - that they contain the correct querystring
        - that the list of objects matches

        """

        small_list_view = self.DummyListView.as_view()
        big_list_view = self.DummyListView.as_view(paginate_by=20)

        request_factory = RequestFactory()

        # tests without querystring only one page
        request = request_factory.get('/fake-path')
        response = big_list_view(request).render()
        self.assertFalse(hasattr(response.context_data['page_obj'], 'next_url'))
        self.assertFalse(hasattr(response.context_data['page_obj'], 'previous_url'))
        self.assertEqual(len(response.context_data['object_list']), 19)

        # tests without querystring first page
        request = request_factory.get('/fake-path')
        response = small_list_view(request).render()

        self.assertEqual(response.context_data['page_obj'].next_url, "page=2")
        self.assertFalse(response.context_data['page_obj'].previous_url)
        self.assertEqual(len(response.context_data['object_list']), 4)
        response_content = str(response.content)
        self.assertIn('<a href="?page=2">', response_content)

        # tests without querystring second page
        request = request_factory.get('/fake-path?page=2')
        response = small_list_view(request).render()

        self.assertEqual(response.context_data['page_obj'].next_url, "page=3")
        self.assertEqual(response.context_data['page_obj'].previous_url, "page=1")
        self.assertEqual(len(response.context_data['object_list']), 4)
        response_content = str(response.content)
        self.assertIn('<a href="?page=3">', response_content)
        self.assertIn('<a href="?page=1">', response_content)

        # tests without querystring last page
        request = request_factory.get('/fake-path?page=5')
        response = small_list_view(request).render()

        self.assertFalse(response.context_data['page_obj'].next_url)
        self.assertEqual(response.context_data['page_obj'].previous_url, "page=4")
        self.assertEqual(len(response.context_data['object_list']), 3)
        response_content = str(response.content)
        self.assertIn('<a href="?page=4">', response_content)

        # tests with querystring only one page
        request = request_factory.get('/fake-path?query=hell0')
        response = big_list_view(request).render()
        self.assertFalse(hasattr(response.context_data['page_obj'], 'next_url'))
        self.assertFalse(hasattr(response.context_data['page_obj'], 'previous_url'))
        self.assertEqual(len(response.context_data['object_list']), 19)

        # tests with querystring first page
        request = request_factory.get('/fake-path?query=hello')
        response = small_list_view(request).render()

        self.assertIn("page=2", response.context_data['page_obj'].next_url)
        self.assertIn("query=hello", response.context_data['page_obj'].next_url)
        self.assertFalse(response.context_data['page_obj'].previous_url)
        self.assertEqual(len(response.context_data['object_list']), 4)
        response_content = str(response.content)
        # we cannot know the order of the query string parameters
        if '<a href="?page=2&amp;query=hello">' not in response_content \
                and '<a href="?query=hello&amp;page=2">' not in response_content:
            self.fail('No link found with`page=2` and `query=hello` ')

        # tests with querystring second page
        request = request_factory.get('/fake-path?query=hello&page=2')
        response = small_list_view(request).render()

        self.assertIn("page=3", response.context_data['page_obj'].next_url)
        self.assertIn("page=1", response.context_data['page_obj'].previous_url)
        self.assertIn("query=hello", response.context_data['page_obj'].next_url)
        self.assertIn("query=hello", response.context_data['page_obj'].previous_url)
        self.assertEqual(len(response.context_data['object_list']), 4)
        response_content = str(response.content)
        # we cannot know the order of the query string parameters
        if '<a href="?page=3&amp;query=hello">' not in response_content \
                and '<a href="?query=hello&amp;page=3">' not in response_content:
            self.fail('No link found with`page=3` and `query=hello` ')
        if '<a href="?page=1&amp;query=hello">' not in response_content \
                and '<a href="?query=hello&amp;page=1">' not in response_content:
            self.fail('No link found with`page=1` and `query=hello` ')

        # tests with querystring last  page
        request = request_factory.get('/fake-path?query=hello&page=5')
        response = small_list_view(request).render()

        self.assertFalse(response.context_data['page_obj'].next_url)
        self.assertIn("page=4", response.context_data['page_obj'].previous_url)
        self.assertIn("query=hello", response.context_data['page_obj'].previous_url)
        self.assertEqual(len(response.context_data['object_list']), 3)
        response_content = str(response.content)
        # we cannot know the order of the query string parameters
        if '<a href="?page=4&amp;query=hello">' not in response_content \
                and '<a href="?query=hello&amp;page=4">' not in response_content:
            self.fail('No link found with`page=4` and `query=hello` ')

    def test_pagination_buttons(self):
        """Test the `{% pagination %}` templatetag with a tied form, using buttons

        We test:
        - a big page without pagination
        - the first page
        - a page in the middle
        - the last page

        Each time we check for
        - that the button(s) are present
        - with the correct page number
        - that they are tied to the form
        - that the list of objects matches

        """

        small_list_view = self.DummyListView.as_view(
            template_name='test/test_pagination_with_form_id.html'
        )
        big_list_view = self.DummyListView.as_view(
            template_name='test/test_pagination_with_form_id.html',
            paginate_by=20
        )

        request_factory = RequestFactory()

        # tests only one page
        request = request_factory.get('/fake-path')
        response = big_list_view(request).render()
        self.assertFalse(hasattr(response.context_data['page_obj'], 'next_number'))
        self.assertFalse(hasattr(response.context_data['page_obj'], 'previous_number'))
        self.assertEqual(len(response.context_data['object_list']), 19)

        # tests first page
        request = request_factory.get('/fake-path')
        response = small_list_view(request).render()

        self.assertEqual(response.context_data['page_obj'].next_number, 2)
        self.assertFalse(response.context_data['page_obj'].previous_number)
        self.assertEqual(len(response.context_data['object_list']), 4)
        response_content = str(response.content)
        self.assertIn(
            '<button type="submit" form="some-form" name="page" value="2">',
            response_content
        )

        # tests second page
        request = request_factory.get('/fake-path?page=2')
        response = small_list_view(request).render()

        self.assertEqual(response.context_data['page_obj'].next_number, 3)
        self.assertEqual(response.context_data['page_obj'].previous_number, 1)
        self.assertEqual(len(response.context_data['object_list']), 4)
        response_content = str(response.content)
        self.assertIn(
            '<button type="submit" form="some-form" name="page" value="3">',
            response_content
        )
        self.assertIn(
            '<button type="submit" form="some-form" name="page" value="1">',
            response_content
        )

        # tests last page
        request = request_factory.get('/fake-path?page=5')
        response = small_list_view(request).render()

        self.assertFalse(response.context_data['page_obj'].next_number)
        self.assertEqual(response.context_data['page_obj'].previous_number, 4)
        self.assertEqual(len(response.context_data['object_list']), 3)
        response_content = str(response.content)
        self.assertIn(
            '<button type="submit" form="some-form" name="page" value="4">',
            response_content
        )

