import re


inlineRegex = r"""
(?P<em>[*_]{1,7}) (?P<textEm>(?:\\[*]|[^*])*) (?P=em)                              # emphasis
|
[`] (?P<textCode>(?:\\[`]|[^`])*) [`]                                              # inline code
|
(?P<imageFlag>!?) \[ (?P<urlText>[^\[\]]*) \] \((?P<urlDestination>[^\(\)]*)\)     # hyperlink or media
|
(?P<strike>~{2}) (?P<textStrike>(?:\\[~]|[^~])*) (~{2})                            # strikethrough
|
(?P<diff>\-\-|\+\+) (?P<textDiff>(?:\\[-+]|[^-+])*) (?P=diff)                      # diffs
"""


def leading(string, character):
    return len(string) - len(string.lstrip(character))


def trailing(string, character):
    return len(string) - len(string.rstrip(character))


class Element:
    def __init__(self):
        pass

    def __repr__(self):
        return "Void block"


class Heading(Element):
    def __init__(self, content, level):
        super().__init__()
        self.content = content
        self.level = level
        pass

    def __repr__(self):
        return f"Heading level {self.level}:\n\t" + self.content


class Paragraph(Element):
    def __init__(self, content):
        super().__init__()
        self.content = content

    def addLine(self, content):
        self.content += content.strip() + " "

    def __repr__(self):
        return "Paragraph:\n\t" + self.content


class Emphasis(Element):
    def __init__(self, content, value):
        super().__init__()
        self.content = content
        self.value = value

    def __repr__(self):
        return f"Emphasis ({self.value}): " + self.content


def _parse_line(source):
    if trailing(source, "\\") == 1:
        source = source.rstrip("\\")
        source += "\n"

    tokens = []
    pattern = re.compile(inlineRegex, re.MULTILINE | re.DOTALL | re.VERBOSE)
    matches = pattern.finditer(source)

    lookup = 0
    for i in matches:
        l = i.start()
        r = i.end()
        tokens.append(source[lookup:l])

        lookup = r

        if i.group("em"):
            tokens.append(Emphasis(i.group("textEm"), len(i.group("em"))))

    tokens.append(source[lookup:])

    return tokens


def _tokenise(source):
    tokens = []

    current_block = Element

    for line in source.split("\n"):
        if not line.strip():
            # Void block

            tokens.append(current_block)
            current_block = Element()
        elif line.startswith("#") and leading(line.lstrip("#"), " ") == 1:
            tokens.append(current_block)

            content = line.lstrip("#").strip()
            current_block = Heading(content, leading(line, "#"))
        else:
            if not isinstance(current_block, Paragraph):
                # Paragraph is default

                tokens.append(current_block)
                current_block = Paragraph("")

            current_block.addLine(line)

    tokens.append(current_block)

    return tokens


for i in _tokenise(
    """
# Hello World!
## Title 1
### Part 1
#### Chapter 1
##### Article 1
###### Section 1
Lorem ipsum
dolor sit amet

..."""
):
    print(repr(i))


def parse_markdown(source):
    tokens = _tokenise(source)


parse_markdown("")
print(_parse_line("**bold** text"))
