from django.db import models
from django.utils.safestring import mark_safe

from markdownx.models import MarkdownxField

# from markdownx.utils import markdownify
import markdown2
import re

markdowner = markdown2.Markdown(
    extras=['code-friendly', 'fenced-code-blocks', 'numbering', 'tables']
)


def md(s):
    t = markdowner.convert(s)
    t = re.sub(
        r'<code>(.*?)</code>',
        r'<span class="latex"><code>\1</code></span>',
        t,
        flags=re.M + re.DOTALL,
    )
    return mark_safe(t)


class Option(models.Model):
    package = models.ForeignKey('Package', models.CASCADE)
    code = models.CharField(max_length=24)
    description = MarkdownxField()

    def __str__(self):
        return f"[{self.package.name}] {self.code}"

    @property
    def md_description(self):
        return md(self.description)

    class Meta:
        ordering = ['package', 'code']


class Category(models.Model):
    name = models.CharField(max_length=24)

    def __str__(self):
        return self.name

    class Meta:
        verbose_name_plural = "categories"
        ordering = [
            'name',
        ]


class Package(models.Model):
    name = models.CharField(max_length=64)
    category = models.ManyToManyField(Category)
    description = MarkdownxField()
    examples = MarkdownxField(null=True, blank=True)
    comment = models.CharField(max_length=80, blank=True)
    initialization = models.TextField(blank=True)

    def __str__(self):
        cats = [str(x.name) for x in self.category.iterator()]
        return f"[{', '.join(cats)}] {self.name}"

    @property
    def md_description(self):
        return md(self.description)

    @property
    def md_examples(self):
        return md(self.examples)

    @property
    def code(self):
        comment_col = 36
        lines = [
            ["\\usepackage", ""],
        ]
        opts = [
            [option.code, option.description.split('\n')[0]]
            for option in self.option_set.all()
        ]
        if len(opts) == 0:
            lines[0][0] += "{%s}" % self.name
            lines[0][1] = self.comment
        else:
            lines[0][0] += '['
            for o in opts:
                o[0] = "    " + o[0]
            lines.extend(opts)
            lines.append(["]{%s}" % self.name, self.comment])

        finished = [f"{x[0]:<{comment_col}}% {x[1]}" if x[1] else x[0] for x in lines]
        return "\n".join(finished)

    class Meta:
        ordering = [
            'name',
        ]


class Facet(models.Model):
    name = models.CharField(max_length=64)
    packages = models.ManyToManyField(Package)
    description = MarkdownxField()

    @property
    def md_description(self):
        return md(self.description)


class Template(models.Model):
    name = models.CharField(max_length=32)
    description = MarkdownxField()
    packages = models.TextField()
    template = models.TextField()

    def __str__(self):
        return self.name

    @property
    def md_description(self):
        return md(self.description)
