# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from unittest import skipIf

try:
    from django.core.urlresolvers import reverse
except ModuleNotFoundError:
    from django.urls import reverse
from django.db import transaction
from aldryn_reversion.core import create_revision as aldryn_create_revision
from parler.utils.context import switch_language
import six

from . import NewsBlogTestCase
from aldryn_newsblog.cms_appconfig import NewsBlogConfig
from ..settings import ENABLE_REVERSION

if ENABLE_REVERSION:
    try:
        from reversion import create_revision
        from reversion import default_revision_manager
    except ImportError:
        from reversion.revisions import create_revision
        from reversion.revisions import default_revision_manager


@skipIf(not ENABLE_REVERSION, 'django-reversion not enabled')
class TestVersioning(NewsBlogTestCase):
    def create_revision(self, article, content=None, language=None, **kwargs):
        with transaction.atomic():
            with create_revision():
                for k, v in six.iteritems(kwargs):
                    setattr(article, k, v)
                if content:
                    plugins = article.content.get_plugins()
                    plugin = plugins[0].get_plugin_instance()[0]
                    plugin.body = content
                    plugin.save()
                # TODO: Cover both cases (plugin modification/recreation)
                # if content:
                #     article.content.get_plugins().delete()
                #     api.add_plugin(article.content, 'TextPlugin',
                #                    self.language, body=content)
                article.save()

    def revert_to(self, article, revision):
        (default_revision_manager.get_for_object(article)[revision]
                                 .revision.revert())

    def test_revert_revision(self):
        title1 = self.rand_str(prefix='title1_')
        title2 = self.rand_str(prefix='title2_')

        content0 = self.rand_str(prefix='content0_')
        content1 = self.rand_str(prefix='content1_')
        content2 = self.rand_str(prefix='content2_')

        article = self.create_article(content=content0)

        # Revision 1
        self.create_revision(article, title=title1, content=content1)

        response = self.client.get(article.get_absolute_url())
        self.assertContains(response, title1)
        self.assertContains(response, content1)
        self.assertNotContains(response, content0)

        # Revision 2
        self.create_revision(article, title=title2, content=content2)

        response = self.client.get(article.get_absolute_url())
        self.assertContains(response, title2)
        self.assertContains(response, content2)
        self.assertNotContains(response, content1)

        # Revert to revision 1
        self.revert_to(article, 1)

        response = self.client.get(article.get_absolute_url())
        self.assertContains(response, title1)
        self.assertContains(response, content1)
        self.assertNotContains(response, content0)
        self.assertNotContains(response, content2)

    def test_revert_translated_revision(self):
        title1_en = self.rand_str(prefix='title1_en_')
        title1_de = self.rand_str(prefix='title1_de_')
        title2_en = self.rand_str(prefix='title2_en_')
        title2_de = self.rand_str(prefix='title2_de_')

        article = self.create_article()

        # Revision 1
        article.set_current_language('en')
        self.create_revision(article, title=title1_en)

        article.set_current_language('de')
        self.create_revision(article, title=title1_de)

        with switch_language(article, 'en'):
            response = self.client.get(article.get_absolute_url())
            self.assertContains(response, title1_en)

        with switch_language(article, 'de'):
            response = self.client.get(article.get_absolute_url())
            self.assertContains(response, title1_de)

        # Revision 2a (modify just EN)
        article.set_current_language('en')
        self.create_revision(article, title=title2_en)

        response = self.client.get(article.get_absolute_url())
        self.assertContains(response, title2_en)

        with switch_language(article, 'de'):
            response = self.client.get(article.get_absolute_url())
            self.assertContains(response, title1_de)

        # Revision 2b (modify just DE)
        article.set_current_language('de')
        self.create_revision(article, title=title2_de)

        with switch_language(article, 'en'):
            response = self.client.get(article.get_absolute_url())
            self.assertContains(response, title2_en)

        with switch_language(article, 'de'):
            response = self.client.get(article.get_absolute_url())
            self.assertContains(response, title2_de)

        # Revert to revision 2a (EN=2, DE=1)
        self.revert_to(article, 1)

        with switch_language(article, 'en'):
            response = self.client.get(article.get_absolute_url())
            self.assertContains(response, title2_en)

        with switch_language(article, 'de'):
            response = self.client.get(article.get_absolute_url())
            self.assertContains(response, title1_de)

        # Revert to revision 1 (EN=1, DE=1)
        self.revert_to(article, 2)

        with switch_language(article, 'en'):
            response = self.client.get(article.get_absolute_url())
            self.assertContains(response, title1_en)

        with switch_language(article, 'de'):
            response = self.client.get(article.get_absolute_url())
            self.assertContains(response, title1_de)

    def test_edit_plugin_directly(self):
        content0 = self.rand_str(prefix='content0_')
        content1 = self.rand_str(prefix='content1_')
        content2 = self.rand_str(prefix='content2_')

        article = self.create_article(content=content0)

        # Revision 1
        self.create_revision(article, content=content1)

        self.assertEqual(
            len(default_revision_manager.get_for_object(article)), 1)

        # Revision 2
        with transaction.atomic():
            plugins = article.content.get_plugins()
            plugin = plugins[0].get_plugin_instance()[0]
            plugin.body = content2
            plugin.save()
            aldryn_create_revision(article)

        self.assertEqual(
            len(default_revision_manager.get_for_object(article)), 2)

        response = self.client.get(article.get_absolute_url())
        self.assertContains(response, content2)
        self.assertNotContains(response, content1)

        # Revert to revision 1
        self.revert_to(article, 1)

        response = self.client.get(article.get_absolute_url())
        self.assertContains(response, content1)
        self.assertNotContains(response, content2)

    def test_blog_config_recovery_accessible(self):
        with transaction.atomic():
            with create_revision():
                new_conf = NewsBlogConfig(
                    namespace='test_revocery_admin_url', paginate_by=15)
                new_conf.save()
        new_config_version = (default_revision_manager
                              .get_for_object(new_conf)[0])
        new_config_pk = new_conf.pk
        self.assertEqual(NewsBlogConfig.objects.filter(
            pk=new_config_pk).count(), 1)
        new_conf.delete()
        self.assertEqual(NewsBlogConfig.objects.filter(
            pk=new_config_pk).count(), 0)

        # check that there is a a way to access recovery view
        obj = new_config_version.object_version.object
        opts = obj._meta
        url = reverse(
            'admin:{0}_{1}_{2}'.format(
                opts.app_label,
                obj._meta.model_name,
                'recover'),
            args=[new_config_version.pk])
        # ust in case check the length, but at this step either a
        # NoReverseMatch should occur or other error,
        # if no exception is raised, it is a good sign
        self.assertGreater(len(url), 4)

[((791, 851), 'unittest.skipIf', 'skipIf', (['(not ENABLE_REVERSION)', '"""django-reversion not enabled"""'], {}), "(not ENABLE_REVERSION, 'django-reversion not enabled')\n", (797, 851), False, 'from unittest import skipIf\n'), ((984, 1004), 'django.db.transaction.atomic', 'transaction.atomic', ([], {}), '()\n', (1002, 1004), False, 'from django.db import transaction\n'), ((3684, 3714), 'parler.utils.context.switch_language', 'switch_language', (['article', '"""en"""'], {}), "(article, 'en')\n", (3699, 3714), False, 'from parler.utils.context import switch_language\n'), ((3850, 3880), 'parler.utils.context.switch_language', 'switch_language', (['article', '"""de"""'], {}), "(article, 'de')\n", (3865, 3880), False, 'from parler.utils.context import switch_language\n'), ((4267, 4297), 'parler.utils.context.switch_language', 'switch_language', (['article', '"""de"""'], {}), "(article, 'de')\n", (4282, 4297), False, 'from parler.utils.context import switch_language\n'), ((4571, 4601), 'parler.utils.context.switch_language', 'switch_language', (['article', '"""en"""'], {}), "(article, 'en')\n", (4586, 4601), False, 'from parler.utils.context import switch_language\n'), ((4737, 4767), 'parler.utils.context.switch_language', 'switch_language', (['article', '"""de"""'], {}), "(article, 'de')\n", (4752, 4767), False, 'from parler.utils.context import switch_language\n'), ((4984, 5014), 'parler.utils.context.switch_language', 'switch_language', (['article', '"""en"""'], {}), "(article, 'en')\n", (4999, 5014), False, 'from parler.utils.context import switch_language\n'), ((5150, 5180), 'parler.utils.context.switch_language', 'switch_language', (['article', '"""de"""'], {}), "(article, 'de')\n", (5165, 5180), False, 'from parler.utils.context import switch_language\n'), ((5396, 5426), 'parler.utils.context.switch_language', 'switch_language', (['article', '"""en"""'], {}), "(article, 'en')\n", (5411, 5426), False, 'from parler.utils.context import switch_language\n'), ((5562, 5592), 'parler.utils.context.switch_language', 'switch_language', (['article', '"""de"""'], {}), "(article, 'de')\n", (5577, 5592), False, 'from parler.utils.context import switch_language\n'), ((6182, 6202), 'django.db.transaction.atomic', 'transaction.atomic', ([], {}), '()\n', (6200, 6202), False, 'from django.db import transaction\n'), ((6386, 6417), 'aldryn_reversion.core.create_revision', 'aldryn_create_revision', (['article'], {}), '(article)\n', (6408, 6417), True, 'from aldryn_reversion.core import create_revision as aldryn_create_revision\n'), ((6974, 6994), 'django.db.transaction.atomic', 'transaction.atomic', ([], {}), '()\n', (6992, 6994), False, 'from django.db import transaction\n'), ((7210, 7259), 'reversion.revisions.default_revision_manager.get_for_object', 'default_revision_manager.get_for_object', (['new_conf'], {}), '(new_conf)\n', (7249, 7259), False, 'from reversion.revisions import default_revision_manager\n'), ((1023, 1040), 'reversion.revisions.create_revision', 'create_revision', ([], {}), '()\n', (1038, 1040), False, 'from reversion.revisions import create_revision\n'), ((1070, 1091), 'six.iteritems', 'six.iteritems', (['kwargs'], {}), '(kwargs)\n', (1083, 1091), False, 'import six\n'), ((6093, 6141), 'reversion.revisions.default_revision_manager.get_for_object', 'default_revision_manager.get_for_object', (['article'], {}), '(article)\n', (6132, 6141), False, 'from reversion.revisions import default_revision_manager\n'), ((6461, 6509), 'reversion.revisions.default_revision_manager.get_for_object', 'default_revision_manager.get_for_object', (['article'], {}), '(article)\n', (6500, 6509), False, 'from reversion.revisions import default_revision_manager\n'), ((7013, 7030), 'reversion.revisions.create_revision', 'create_revision', ([], {}), '()\n', (7028, 7030), False, 'from reversion.revisions import create_revision\n'), ((7059, 7126), 'aldryn_newsblog.cms_appconfig.NewsBlogConfig', 'NewsBlogConfig', ([], {'namespace': '"""test_revocery_admin_url"""', 'paginate_by': '(15)'}), "(namespace='test_revocery_admin_url', paginate_by=15)\n", (7073, 7126), False, 'from aldryn_newsblog.cms_appconfig import NewsBlogConfig\n'), ((7356, 7403), 'aldryn_newsblog.cms_appconfig.NewsBlogConfig.objects.filter', 'NewsBlogConfig.objects.filter', ([], {'pk': 'new_config_pk'}), '(pk=new_config_pk)\n', (7385, 7403), False, 'from aldryn_newsblog.cms_appconfig import NewsBlogConfig\n'), ((7480, 7527), 'aldryn_newsblog.cms_appconfig.NewsBlogConfig.objects.filter', 'NewsBlogConfig.objects.filter', ([], {'pk': 'new_config_pk'}), '(pk=new_config_pk)\n', (7509, 7527), False, 'from aldryn_newsblog.cms_appconfig import NewsBlogConfig\n'), ((1749, 1797), 'reversion.revisions.default_revision_manager.get_for_object', 'default_revision_manager.get_for_object', (['article'], {}), '(article)\n', (1788, 1797), False, 'from reversion.revisions import default_revision_manager\n')]