# Original source: https://brandonjay.dev/posts/2021/render-markdown-html-in-python-with-jinja2

from types import SimpleNamespace
from html import escape
from app.cache import time_cache_async
from mistune import HTMLRenderer, Markdown
from pygments import highlight
from pygments.formatters import html
from pygments.lexers import get_lexer_by_name


class MarkdownRenderer(HTMLRenderer):

    _allow_harmful_protocols = True

    def __init__(self, app, template):
        self.template = template

        self.app = app
        self.env = self.app.jinja2_env
        formatter = html.HtmlFormatter()
        self.env.globals["highlight_styles"] = formatter.get_style_defs()

    def _escape(self, str):
        return str  ##escape(str)

    def get_lexer(self, lang, default='bash'):
        try:
            return get_lexer_by_name(lang, stripall=True)
        except:
            return get_lexer_by_name(default, stripall=True)
    
    def block_code(self, code, lang=None, info=None):
        if not lang:
            lang = info
        if not lang:
            lang = 'bash'
        lexer = self.get_lexer(lang)
        formatter = html.HtmlFormatter(lineseparator="<br>")
        result = highlight(code, lexer, formatter)
        return result 

    def render(self):
        markdown_string = self.app.template_path.joinpath(self.template).read_text()
        renderer = MarkdownRenderer(self.app, self.template)
        markdown = Markdown(renderer=renderer)
        return markdown(markdown_string)


def render_markdown_sync(app, markdown_string):
    renderer = MarkdownRenderer(app, None)
    markdown = Markdown(renderer=renderer)
    return markdown(markdown_string)


@time_cache_async(120)
async def render_markdown(app, markdown_string):
    return render_markdown_sync(app, markdown_string)


from jinja2 import TemplateSyntaxError, nodes
from jinja2.ext import Extension
from jinja2.nodes import Const


# Source: https://ron.sh/how-to-write-a-jinja2-extension/
class MarkdownExtension(Extension):
    tags = {"markdown"}

    def __init__(self, environment):
        self.app = SimpleNamespace(jinja2_env=environment)
        super(MarkdownExtension, self).__init__(environment)

    def parse(self, parser):
        line_number = next(parser.stream).lineno
        md_file = [Const("")]
        body = ""
        try:
            md_file = [parser.parse_expression()]
        except TemplateSyntaxError:
            body = parser.parse_statements(["name:endmarkdown"], drop_needle=True)
        return nodes.CallBlock(
            self.call_method("_to_html", md_file), [], [], body
        ).set_lineno(line_number)

    def _to_html(self, md_file, caller):
        return render_markdown_sync(self.app, caller())
