from django.db import models
from django.utils.safestring import mark_safe
from django.contrib.auth.models import Group

import base64
import markdown2
import re

from markdownx.models import MarkdownxField
from mpl.generate import generate

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

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


class Graph(models.Model):
    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)
    description = MarkdownxField()
    code = models.TextField()
    thumbnail = models.BinaryField(blank=True, null=True)
    mime = models.CharField(max_length=12, default='webp')
    keywords = models.CharField(max_length=255, blank=True)
    permission = models.ForeignKey(Group, on_delete=models.CASCADE, blank=True, null=True)

    def __str__(self):
        if self.description:
            return self.description
        return f"Graph {self.id}"

    def isaccessible(self, request):
        if self.permission is None:
            return True
        return self.permission in request.user.groups.all()

    def html(self, **kwargs):
        properties = []
        if 'width' in kwargs:
            w = kwargs['width']
            if isinstance(w, float):
                properties.append(f'width="{100*w}%"')
            elif isinstance(w, int):
                properties.append(f'width="{w}px"')
        try:
            bits = base64.encodebytes(self.thumbnail)
            s = f'<img src="data:image/{self.mime};base64,{bits.decode()}"'
            if properties:
                t = "".join(properties)
                s += ' ' + t
            return mark_safe(s + '>')
        except:
            attempt = generate(self)
            if 'error' in attempt:
                return mark_safe(f"<code>{attempt['error']}</code>" )

    def full(self):
        return self.html(width=1.0)

    def save(self, *args, **kwargs):
        attempt = generate(self)
        if 'ext' in attempt:
            self.mime = attempt['ext'][1:]
            self.thumbnail = attempt['graphic']
        super().save(*args, **kwargs)

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

    class Meta:
        ordering = [
            '-modified',
        ]


class Tip(models.Model):
    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)
    name = models.CharField(max_length=255)
    description = MarkdownxField()

    def __str__(self):
        return self.name

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

    class Meta:
        ordering = [
            '-modified',
        ]
