import re
from html.parser import HTMLParser

from gi.repository import GLib  # type: ignore


def bind_list(lst: list) -> str:
    "Small util to bind list in a query"
    return ",".join("?" * len(lst))


def convert_markdown_links(text):
    """converts markdown links to html hyperlinks"""
    return re.sub(r"\[([^]]+?)\]\(([^)\s]+?)(?:\s.*?)?\)", r'<a href="\2">\1</a>', text)


def clean_markup(text):
    """remove unsupported markup from text to use in label"""
    if text is None:
        text = ""

    text = html2pango(text)
    text = text.replace("\n\n\n", "\n\n")
    text = text.replace("&lt;", "§lt;").replace("&gt;", "§gt;")
    text = text.replace("&", "&amp;")
    text = text.replace("§lt;", "&lt;").replace("§gt;", "&gt;")

    return text.strip()


def markup_to_text(text):
    """return plain text version of markup string"""
    text = clean_markup(f"<div>{text}</div>")
    text = re.sub(r'</?i>', '_', text)
    text = re.sub(r'</?tt>', '`', text)
    text = re.sub(r'</?b>', '**', text)
    text = text.replace("&amp;", "&")

    # remove all remainig tags
    text = re.sub(r'</?\w+[^>]*>', '', text)
    return text


class InterruptibleTimeout:
    def __init__(self, intervall=0, callback=None, data=None):
        self._running = False
        self._requested_stop = True
        self._callback = callback
        if callback:
            self._running = True
            self._requested_stop = False
            if callback(self, data):
                GLib.timeout_add(intervall, self._on_timeout, data)

    def _on_timeout(self, data):
        if self._requested_stop:
            res = False
        else:
            res = self._callback(self, data)
        self._running = res
        return res

    def stop(self):
        self._requested_stop = True

    def must_stop(self):
        return self._requested_stop


# pango tags:
TAG_MAP = {
    # pango tags, as is
    'b': ('<b>', '</b>'),
    'i': ('<i>', '</i>'),
    's': ('<s>', '</s>'),
    'sub': ('<sub>', '</sub>'),
    'sup': ('<sup>', '</sup>'),
    'big': ('<big>', '</big>'),
    'small': ('<small>', '</small>'),
    'tt': ('<tt>', '</tt>'),
    'u': ('<u>', '</u>'),

    # blocks
    'address': ('', '\n\n'),
    'blockquote': ('', '\n\n'),
    'div': ('', '\n\n'),
    'footer': ('', '\n\n'),
    'header': ('', '\n\n'),
    # 'hr': ('', '<span qualcosa>'),
    'p': ('', '\n\n'),
    'pre': ('\n<tt>', '</tt>\n'),


    'h1': ('<big><b>', '</b></big>\n\n'),
    'h2': ('<b>', '</b>\n\n'),
    'h3': ('<b>', '</b>\n\n'),
    'h4': ('<small><b>', '</b></small>\n\n'),
    'h5': ('<small><b>', '</b></small>\n\n'),
    'h6': ('<small><b>', '</b></small>\n\n'),
    'td': ('<tt>', '</tt>'),
    'th': ('<b><tt>', '</tt></b>'),
    'tr': ('', '\n'),
    'dt': ('<b>', '<b>'),
    'dd': ('    ', '\n'),
    'li': ('', '\n'),

    # inline
    'em': ('<i>', '</i>'),
    'var': ('<i><tt>', '</tt></i>'),
    'kbd': ('<i><tt>', '</tt></i>'),
    'code': ('<tt>', '</tt>'),
    'strong': ('<b>', '</b>'),
    # a
    'ins': ('<u>', '</u>'),
    'del': ('<s>', '</s>'),
    'strike': ('<s>', '</s>'),
    'br': ('', '\n'),
}


class HTMLToPango(HTMLParser):
    def __init__(self):
        super().__init__()
        self.result = []

    def a_s(self, tag, attrs):
        href = attrs.get('href', '')
        self.result.append(f'<a href="{href}">')

    def a_e(self, tag):
        self.result.append('</a>')

    def handle_starttag(self, tag, attrs):
        attrs = dict(attrs)
        if tag in TAG_MAP:
            self.result.append(TAG_MAP[tag][0])
            return

        f = getattr(self, f"{tag}_s", None)
        if f:
            f(tag, attrs)
            return

        self.result.append(self.get_starttag_text().replace("<", "&lt;").replace(">", "&gt;"))

    def handle_endtag(self, tag):
        if tag in TAG_MAP:
            self.result.append(TAG_MAP[tag][1])
            return

        f = getattr(self, f"{tag}_e", None)
        if f:
            f(tag)
            return

        self.result.append(f"&lt;/{tag}&gt;")

    def handle_data(self, data):
        self.result.append(data.strip())


def html2pango(text):
    parser = HTMLToPango()
    parser.feed(text)
    return ''.join(parser.result)
