# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0

import logging as log
import re


def expand_paras(s, rnames):
    '''Expand a description field to HTML.

    This supports a sort of simple pseudo-markdown. Supported Markdown
    features:

    - Separate paragraphs on a blank line
    - **bold** and *italicised* text
    - Back-ticks for pre-formatted text

    We also generate links to registers when a name is prefixed with a double
    exclamation mark. For example, if there is a register FOO then !!FOO or
    !!FOO.field will generate a link to that register.

    Returns a list of rendered paragraphs

    '''
    # Start by splitting into paragraphs. The regex matches a newline followed
    # by one or more lines that just contain whitespace. Then render each
    # paragraph with the _expand_paragraph worker function.
    paras = [_expand_paragraph(paragraph.strip(), rnames)
             for paragraph in re.split(r'\n(?:\s*\n)+', s)]

    # There will always be at least one paragraph (splitting an empty string
    # gives [''])
    assert paras
    return paras


def _expand_paragraph(s, rnames):
    '''Expand a single paragraph, as described in _get_desc_paras'''
    def fieldsub(match):
        base = match.group(1).partition('.')[0].lower()
        if base in rnames:
            if match.group(1)[-1] == ".":
                return ('<a href="#Reg_' + base + '"><code class=\"reg\">' +
                        match.group(1)[:-1] + '</code></a>.')
            else:
                return ('<a href="#Reg_' + base + '"><code class=\"reg\">' +
                        match.group(1) + '</code></a>')
        log.warn('!!' + match.group(1).partition('.')[0] +
                 ' not found in register list.')
        return match.group(0)

    # Split out pre-formatted text. Because the call to re.split has a capture
    # group in the regex, we get an odd number of results. Elements with even
    # indices are "normal text". Those with odd indices are the captured text
    # between the back-ticks.
    code_split = re.split(r'`([^`]+)`', s)
    expanded_parts = []

    for idx, part in enumerate(code_split):
        if idx & 1:
            # Text contained in back ticks
            expanded_parts.append('<code>{}</code>'.format(part))
            continue

        part = re.sub(r"!!([A-Za-z0-9_.]+)", fieldsub, part)
        part = re.sub(r"(?s)\*\*(.+?)\*\*", r'<B>\1</B>', part)
        part = re.sub(r"\*([^*]+?)\*", r'<I>\1</I>', part)
        expanded_parts.append(part)

    return '<p>{}</p>'.format(''.join(expanded_parts))


def render_td(s, rnames, td_class):
    '''Expand a description field and put it in a <td>.

    Returns a string. See _get_desc_paras for the format that gets expanded.

    '''
    desc_paras = expand_paras(s, rnames)
    class_attr = '' if td_class is None else ' class="{}"'.format(td_class)
    return '<td{}>{}</td>'.format(class_attr, ''.join(desc_paras))
