#coding: utf-8

"""
Deals with generating the per-page table of contents.

For the sake of simplicity we use an existing markdown extension to generate
an HTML table of contents, and then parse that into the underlying data.

The steps we take to generate a table of contents are:

* Pre-process the markdown, injecting a [TOC] marker.
* Generate HTML from markdown.
* Post-process the HTML, spliting the content and the table of contents.
* Parse table of contents HTML into the underlying data structure.
"""

import re

TOC_DELIMITER = '<!-- STARTTOC -->'
TOC_LINK_REGEX = re.compile('<a href=["]([^"]*)["]>([^<]*)</a>')


def pre_process(markdown_content):
    """
    Append a `[TOC]` marker to the markdown.
    The `toc` extension injects the HTML table of contents here.
    """
    return markdown_content + '\n\n' + TOC_DELIMITER + '\n[TOC]'


def post_process(html_content):
    """
    Strip the generated HTML table of contents from the HTML output.

    Returns a two-tuple of `(content, table_of_contents)`
    """
    return html_content.rsplit(TOC_DELIMITER, 1)


class TableOfContents(object):
    """
    Represents the table of contents for a given page.
    """
    def __init__(self, html):
        self.items = _parse_html_table_of_contents(html)

    def __iter__(self):
        return iter(self.items)

    def __str__(self):
        return ''.join([str(item) for item in self])


class AnchorLink(object):
    """
    A single entry in the table of contents.
    """
    def __init__(self, title, url):
        self.title, self.url = title, url
        self.children = []

    def __str__(self):
        return self._indent_print()

    def _indent_print(self, depth=0):
        indent = '    ' * depth
        ret = '%s%s - %s\n' % (indent, self.title, self.url)
        for item in self.children:
            ret += item._indent_print(depth + 1)
        return ret


def _parse_html_table_of_contents(html):
    """
    Given a table of contents string that has been automatically generated by
    the markdown library, parse it into a tree of AnchorLink instances.

    Returns a list of all the parent AnchorLink instances.
    """
    lines = html.splitlines()[2:-2]
    parents = []
    ret = []
    for line in lines:
        match = TOC_LINK_REGEX.search(line)
        if match:
            href, title = match.groups()
            nav = AnchorLink(title, href)
            # Add the item to its parent if required.  If it is a topmost
            # item then instead append it to our return value.
            if parents:
                parents[-1].children.append(nav)
            else:
                ret.append(nav)
            # If this item has children, store it as the current parent
            if line.endswith('<ul>'):
                parents.append(nav)
        elif line.startswith('</ul>'):
            parents.pop()

    # For the table of contents, always mark the first element as active
    if ret:
        ret[0].active = True

    return ret
