"""
Simple "flat pages".

These get used for the static (non-automated) large chunks of content. Notice
that pages don't have any actual notion of where they live; instead, they're
positioned into the URL structure using the nav app.
"""

import os
import re

from copy import deepcopy

from django.conf import settings
from django.core import validators
from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver

from markupfield.fields import MarkupField
from markupfield.markup import DEFAULT_MARKUP_TYPES

import cmarkgfm

from cms.models import ContentManageable
from fastly.utils import purge_url

from .managers import PageQuerySet

DEFAULT_MARKUP_TYPE = getattr(settings, 'DEFAULT_MARKUP_TYPE', 'restructuredtext')

PAGE_PATH_RE = re.compile(r"""
    ^
    /?                      # We can optionally start with a /
    ([a-z0-9-\.]+)            # Then at least one path segment...
    (/[a-z0-9-\.]+)*        # And then possibly more "/whatever" segments
    /?                      # Possibly ending with a slash
    $
    """,
    re.X
)

is_valid_page_path = validators.RegexValidator(
    regex=PAGE_PATH_RE,
    message=(
        'Please enter a valid URL segment, e.g. "foo" or "foo/bar". '
        'Only lowercase letters, numbers, hyphens and periods are allowed.'
    ),
)

RENDERERS = deepcopy(DEFAULT_MARKUP_TYPES)
for i, renderer in enumerate(RENDERERS):
    if renderer[0] == 'markdown':
        markdown_index = i

RENDERERS[markdown_index] = (
    'markdown',
    cmarkgfm.github_flavored_markdown_to_html,
    'Markdown'
)


class Page(ContentManageable):
    title = models.CharField(max_length=500)
    keywords = models.CharField(max_length=1000, blank=True, help_text="HTTP meta-keywords")
    description = models.TextField(blank=True, help_text="HTTP meta-description")
    path = models.CharField(max_length=500, validators=[is_valid_page_path], unique=True, db_index=True)
    content = MarkupField(markup_choices=RENDERERS, default_markup_type=DEFAULT_MARKUP_TYPE)
    is_published = models.BooleanField(default=True, db_index=True)
    content_type = models.CharField(max_length=150, default='text/html')
    template_name = models.CharField(
        max_length=100,
        blank=True,
        help_text="Example: 'pages/about.html'. If this isn't provided, the system will use 'pages/default.html'."
    )

    objects = PageQuerySet.as_manager()

    class Meta:
        ordering = ['title', 'path']

    def clean(self):
        # Strip leading and trailing slashes off self.path.
        self.path = self.path.strip('/')

    def get_title(self):
        if self.title:
            return self.title
        else:
            return '** No Title **'

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return f"/{self.path}/"


@receiver(post_save, sender=Page)
def purge_fastly_cache(sender, instance, **kwargs):
    """
    Purge fastly.com cache if in production and the page is published.
    Requires settings.FASTLY_API_KEY being set
    """
    purge_url(f'/{instance.path}')


def page_image_path(instance, filename):
    return os.path.join(instance.page.path, filename)


class Image(models.Model):
    page = models.ForeignKey('pages.Page', on_delete=models.CASCADE)
    image = models.ImageField(upload_to=page_image_path, max_length=400)

    def __str__(self):
        return self.image.url


class DocumentFile(models.Model):
    page = models.ForeignKey('pages.Page', on_delete=models.CASCADE)
    document = models.FileField(upload_to='files/', max_length=500)

    def __str__(self):
        return self.document.url


@@ -573,16 +573,70 @@
 cmarkgfm
+%0Afrom cmarkgfm.cmark import Options as cmarkgfmOptions
 %0A%0Afrom c
@@ -826,16 +826,191 @@
 text')%0A%0A
+# Set options for cmarkgfm for %22unsafe%22 renderer, see https://github.com/theacodes/cmarkgfm#advanced-usage%0ACMARKGFM_UNSAFE_OPTIONS = (%0A    cmarkgfmOptions.CMARK_OPT_UNSAFE%0A)%0A%0A
 PAGE_PAT
@@ -1826,16 +1826,226 @@
 own'%0A)%0A%0A
+RENDERERS.append(%0A    (%0A        %22markdown_unsafe%22,%0A        lambda markdown_text: cmarkgfm.github_flavored_markdown_to_html(markdown_text, options=CMARKGFM_UNSAFE_OPTIONS),%0A        %22Markdown (unsafe)%22,%0A    )%0A)%0A%0A
 %0Aclass P

configure cmarkgfm to make cms pages more flexible (#2182)