from types import SimpleNamespace
from bs4 import BeautifulSoup
import re 
import emoji

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

emoji.EMOJI_DATA['<img src="/emoji/snek1.gif" />'] = {"en": ":snek1:","status":2,"E":0.6, "alias":[":snek1:"]} 

def set_link_target_blank(text):
    soup = BeautifulSoup(text, 'html.parser')

    for element in soup.find_all("a"):  
        element.attrs['target'] = '_blank'
        element.attrs['rel'] = 'noopener noreferrer'
        element.attrs['referrerpolicy'] = 'no-referrer'
        element.attrs['href'] = element.attrs['href'].strip(".")
        #if element.attrs['href'].startswith("https://www.you") and "?v=" in element.attrs["href"]:
        #    video_name = element.attrs["href"].split("?v=")[1].split("&")[0]
        #    embed_template = f'<iframe width="560" height="315" src="https://www.youtube.com/embed/{video_name}" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>'
        #    element.replace_with(BeautifulSoup(embed_template, 'html.parser'))

    return str(soup)

def embed_youtube(text):
    soup = BeautifulSoup(text, 'html.parser') 
    for element in soup.find_all("a"):  
        if element.attrs['href'].startswith("https://www.you") and "?v=" in element.attrs["href"]:
            video_name = element.attrs["href"].split("?v=")[1].split("&")[0]
            embed_template = f'<iframe width="560" height="315" src="https://www.youtube.com/embed/{video_name}" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>'
            element.replace_with(BeautifulSoup(embed_template, 'html.parser'))
    return str(soup)

def embed_image(text):
    soup = BeautifulSoup(text, 'html.parser') 
    for element in soup.find_all("a"):  
        for extension in [".png", ".jpeg", ".gif", ".webp", ".svg", ".bmp", ".tiff", ".ico", ".heif"]:
            if extension in element.attrs['href'].lower():
                embed_template = f'<img src="{element.attrs["href"]}" title="{element.attrs["href"]}" alt="{element.attrs["href"]}" />'
                element.replace_with(BeautifulSoup(embed_template, 'html.parser'))
    return str(soup)

def embed_media(text):
    soup = BeautifulSoup(text, 'html.parser') 
    for element in soup.find_all("a"):  
        for extension in [".mp4", ".mp3", ".wav", ".ogg", ".webm", ".flac", ".aac",".mpg",".avi",".wmv"]:
            if extension in element.attrs['href'].lower():
                embed_template = f'<video controls> <source src="{element.attrs["href"]}">Your browser does not support the video tag.</video>'
                element.replace_with(BeautifulSoup(embed_template, 'html.parser'))
    return str(soup)



def linkify_https(text):
    if not "https://" in text:
        return text 
    url_pattern = r'(?<!["\'])\bhttps://[^\s<>()]+(?<!\.)'

    soup = BeautifulSoup(text, 'html.parser')

    for element in soup.find_all(text=True):  
        parent = element.parent
        if parent.name in ['a', 'script', 'style']:  
            continue
        
        new_text = re.sub(url_pattern, r'<a href="\g<0>">\g<0></a>', element)
        element.replace_with(BeautifulSoup(new_text, 'html.parser'))

    return set_link_target_blank(str(soup))


class EmojiExtension(Extension):
    tags = {"emoji"}

    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:endemoji"], 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 emoji.emojize(caller(),language='alias')



class LinkifyExtension(Extension):
    tags = {"linkify"}

    def __init__(self, environment):
        self.app = SimpleNamespace(jinja2_env=environment)
        super(LinkifyExtension, 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:endlinkify"], 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):
        result = linkify_https(caller())
        result = embed_media(result)
        result = embed_image(result)
        result = embed_youtube(result)
        return result

class PythonExtension(Extension):
    tags = {"py3"}

    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:endpy3"], 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):
        
        def fn(source):
            import subprocess 
            import subprocess 
            import pathlib 
            from pathlib import Path 
            import os 
            import sys 
            import requests
            def system(command):
                if isinstance(command):
                    command = command.split(" ")
                from io import StringIO 
                stdout = StringIO()
                subprocess.run(command,stderr=stdout,stdout=stdout,text=True)
                return stdout.getvalue()
            to_write = []
            def render(text):
                global to_write 
                to_write.append(text)
            exec(source)
            return "".join(to_write)
        return str(fn(caller()))
