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

from django import template
from django.conf import settings
from django.core.cache import cache
from django.http.cookie import SimpleCookie
from django.test import TestCase
from django.test.client import Client, RequestFactory
from django.test.utils import override_settings
from django.urls import reverse

from ultracache import _thread_locals
from ultracache.tests.models import DummyModel, DummyForeignModel, \
    DummyOtherModel
from ultracache.tests import views
from ultracache.tests.utils import dummy_proxy


class TemplateTagsTestCase(TestCase):
    if "django.contrib.sites" in settings.INSTALLED_APPS:
        fixtures = ["sites.json"]

    @classmethod
    def setUpClass(cls):
        super(TemplateTagsTestCase, cls).setUpClass()
        cls.factory = RequestFactory()
        cls.request = cls.factory.get('/')
        cache.clear()
        dummy_proxy.clear()

    if "django.contrib.sites" in settings.INSTALLED_APPS:
        def test_sites(self):
            from django.contrib.sites.models import Site

            first_site = Site.objects.all().first()
            second_site = Site.objects.all().last()

            # Caching on same site
            t = template.Template("{% load ultracache_tags %}\
                {% ultracache 1200 'test_ultracache' %}1{% endultracache %}"
            )
            context = template.Context({'request' : self.request})
            result1 = t.render(context)
            t = template.Template("{% load ultracache_tags %}\
                {% ultracache 1200 'test_ultracache' %}2{% endultracache %}"
            )
            context = template.Context({'request' : self.request})
            result2 = t.render(context)
            self.failUnlessEqual(result1, result2)

            # Caching on different sites
            t = template.Template("{% load ultracache_tags %}\
                {% ultracache 1200 'test_ultracache' %}1{% endultracache %}"
            )
            context = template.Context({'request' : self.request})
            result1 = t.render(context)
            with override_settings(SITE_ID=second_site.id):
                t = template.Template("{%% load ultracache_tags %%}\
                    {%% ultracache 1200 'test_ultracache' %%}%s{%% endultracache %%}" % second_site.id
                )
                context = template.Context({'request' : self.request})
                result2 = t.render(context)
                self.failIfEqual(result1, result2)

    def test_variables(self):
        # Check that undefined variables do not break caching
        t = template.Template("{% load ultracache_tags %}\
            {% ultracache 1200 'test_ultracache_undefined' aaa %}1{% endultracache %}"
        )
        context = template.Context({'request' : self.request})
        result1 = t.render(context)
        t = template.Template("{% load ultracache_tags %}\
            {% ultracache 1200 'test_ultracache_undefined' bbb %}2{% endultracache %}"
        )
        context = template.Context({'request' : self.request})
        result2 = t.render(context)
        self.failUnlessEqual(result1, result2)

        # Check that translation proxies are valid variables
        t = template.Template("{% load ultracache_tags %}\
            {% ultracache 1200 'test_ultracache_xlt' _('aaa') %}1{% endultracache %}"
        )
        context = template.Context({'request' : self.request})
        result1 = t.render(context)
        t = template.Template("{% load ultracache_tags %}\
            {% ultracache 1200 'test_ultracache_xlt' _('aaa') %}2{% endultracache %}"
        )
        context = template.Context({'request' : self.request})
        result2 = t.render(context)
        self.failUnlessEqual(result1, result2)

        # Check that large integer variables do not break caching
        t = template.Template("{% load ultracache_tags %}\
            {% ultracache 1200 'test_ultracache_large' 565417614189797377 %}abcde{% endultracache %}"
        )
        context = template.Context({'request' : self.request})
        result1 = t.render(context)
        t = template.Template("{% load ultracache_tags %}\
            {% ultracache 1200 'test_ultracache_large' 565417614189797377 %}abcde{% endultracache %}"
        )
        context = template.Context({'request' : self.request})
        result2 = t.render(context)
        self.failUnlessEqual(result1, result2)

    def test_context_without_request(self):
        t = template.Template("{% load ultracache_tags %}\
            {% ultracache 1200 'test_ultracache_undefined' aaa %}abcde{% endultracache %}"
        )
        context = template.Context()
        self.assertRaises(KeyError, t.render, context)

    def test_invalidation(self):
        """Directly render template
        """
        one = DummyModel.objects.create(title='One', code='one')
        two = DummyModel.objects.create(title='Two', code='two')
        three = DummyForeignModel.objects.create(title='Three', points_to=one, code='three')
        four = DummyOtherModel.objects.create(title='Four', code='four')
        # The counter is used to track the iteration that a cached block was
        # last rendered.
        t = template.Template("""{% load ultracache_tags ultracache_test_tags %}
            {% ultracache 1200 'test_ultracache_invalidate_outer' %}
                    counter outer = {{ counter }}
                {% ultracache 1200 'test_ultracache_invalidate_one' %}
                    title = {{ one.title }}
                    counter one = {{ counter }}
                {% endultracache %}
                {% ultracache 1200 'test_ultracache_invalidate_two' %}
                    title = {{ two.title }}
                    counter two = {{ counter }}
                {% endultracache %}
                {% ultracache 1200 'test_ultracache_invalidate_three' %}
                    title = {{ three.title }}
                    {{ three.points_to.title }}
                    counter three = {{ counter }}
                {% endultracache %}
                {% ultracache 1200 'test_ultracache_invalidate_render_view' %}
                    {% render_view 'render-view' %}
                {% endultracache %}
                {% ultracache 1200 'test_ultracache_invalidate_include %}
                    {% include "ultracache/include_me.html" %}
                {% endultracache %}
            {% endultracache %}"""
        )

        # Initial render
        request = self.factory.get('/aaa/')
        context = template.Context({
            'request' : request,
            'one': one,
            'two': two,
            'three': three,
            'counter': 1
        })
        result = t.render(context)
        dummy_proxy.cache(request, result)
        self.failUnless('title = One' in result)
        self.failUnless('title = Two' in result)
        self.failUnless('counter outer = 1' in result)
        self.failUnless('counter one = 1' in result)
        self.failUnless('counter two = 1' in result)
        self.failUnless('counter three = 1' in result)
        self.failUnless('render_view = One' in result)
        self.failUnless('include = One' in result)
        self.failUnless(dummy_proxy.is_cached('/aaa/'))

        # Change object one
        one.title = 'Onxe'
        one.save()
        request = self.factory.ge
t('/bbb/')
        context = template.Context({
            'request' : request,
            'one': one,
            'two': two
,
            'three': three,
            'counter': 2
        })
        result = t.render(context)
        dummy_proxy.cache(request, result)
        self.failUnless('title = Onxe' in result)
        self.failIf('title = One' in result)
        self.failUnless('title = Two' in result)
        self.failUnless('counter outer = 2' in result)
        self.failUnless('counter one = 2' in result)
        self.failUnless('counter two = 1' in result)
        self.failUnless('counter three = 2' in result)
        self.failUnless('render_view = Onxe' in result)
        self.failUnless('include = Onxe' in result)
        self.failIf(dummy_proxy.is_cached('/aaa/'))

        # Change object two
        two.title = 'Twxo'
 