# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
"""
Generate HTML documentation from IpBlock
"""

from typing import Optional, Set, TextIO, List, Union

import mistletoe as mk

from reggen.ip_block import IpBlock
from reggen.html_helpers import expand_paras, render_td, get_reg_link
from reggen.multi_register import MultiRegister
from reggen.reg_block import RegBlock
from reggen.register import Register
from reggen.window import Window


def genout(outfile: TextIO, msg: str) -> None:
    outfile.write(msg)


# Generation of HTML table with register bit-field summary picture
# Max 16-bit wide on one line


def gen_tbl_row(outfile: TextIO, msb: int, width: int, close: bool) -> None:
    if (close):
        genout(outfile, "</tr>\n")
    genout(outfile, "<tr>")
    for x in range(msb, msb - width, -1):
        genout(outfile, "<td class=\"bitnum\">" + str(x) + "</td>")

    genout(outfile, "</tr><tr>")


def gen_html_reg_pic(outfile: TextIO, reg: Register, width: int) -> None:

    if (width > 32):
        bsize = 3
        nextbit = 63
        hdrbits = 16
        nextline = 48
    elif (width > 16):
        bsize = 3
        nextbit = 31
        hdrbits = 16
        nextline = 16
    elif (width > 8):
        bsize = 3
        nextbit = 15
        nextline = 0
        hdrbits = 16
    else:
        bsize = 12
        nextbit = 7
        nextline = 0
        hdrbits = 8

    genout(outfile, "<table class=\"regpic\">")
    gen_tbl_row(outfile, nextbit, hdrbits, False)

    for field in reversed(reg.fields):
        fieldlsb = field.bits.lsb
        fieldwidth = field.bits.width()
        fieldmsb = field.bits.msb
        fname = field.name

        while nextbit > fieldmsb:
            if (nextbit >= nextline) and (fieldmsb < nextline):
                spans = nextbit - (nextline - 1)
            else:
                spans = nextbit - fieldmsb
            genout(
                outfile, "<td class=\"unused\" colspan=" + str(spans) +
                ">&nbsp;</td>\n")
            if (nextbit >= nextline) and (fieldmsb < nextline):
                nextbit = nextline - 1
                gen_tbl_row(outfile, nextbit, hdrbits, True)
                nextline = nextline - 16
            else:
                nextbit = fieldmsb

        while (fieldmsb >= nextline) and (fieldlsb < nextline):
            spans = fieldmsb - (nextline - 1)
            genout(
                outfile, "<td class=\"fname\" colspan=" + str(spans) + ">" +
                fname + "...</td>\n")
            fname = "..." + field.name
            fieldwidth = fieldwidth - spans
            fieldmsb = nextline - 1
            nextline = nextline - 16
            gen_tbl_row(outfile, fieldmsb, hdrbits, True)

        namelen = len(fname)
        if namelen == 0 or fname == ' ':
            fname = "&nbsp;"
        if (namelen > bsize * fieldwidth):
            usestyle = (" style=\"font-size:" + str(
                (bsize * 100 * fieldwidth) / namelen) + "%\"")
        else:
            usestyle = ""

        genout(
            outfile, "<td class=\"fname\" colspan=" + str(fieldwidth) +
            usestyle + ">" + fname + "</td>\n")

        if (fieldlsb == nextline) and nextline > 0:
            gen_tbl_row(outfile, nextline - 1, hdrbits, True)
            nextline = nextline - 16

        nextbit = fieldlsb - 1
    while (nextbit > 0):
        spans = nextbit - (nextline - 1)
        genout(outfile,
               "<td class=\"unused\" colspan=" + str(spans) + ">&nbsp;</td>\n")
        nextbit = nextline - 1
        if (nextline > 0):
            gen_tbl_row(outfile, nextline - 1, hdrbits, True)
            nextline = nextline - 16

    genout(outfile, "</tr></table>")


# Generation of HTML table with header, register picture and details

def gen_html_register_summary(outfile: TextIO,
                              obj_list: List[Union[Window, Register]],
                              comp: str,
                              width: int,
                              rnames: Set[str]) -> None:

    bytew = width // 8
    genout(outfile,
           '<table class="regdef" id="RegSummary_{comp}">\n'
           ' <tr>\n'
           '  <th class="regdef" colspan=4> Summary </th>\n'
           ' </tr>\n'
           ' <tr>\n'
           '  <th class="regdef">Name</th>'
           '  <th class="regdef">Offset</th>'
           '  <th class="regdef">Length</th>'
           '  <th class="regdef">Description</th>'
           ' </tr>\n')

    for obj in obj_list:
        obj_length = bytew if isinstance(obj, Register) else bytew * obj.items
        desc_paras = expand_paras(obj.desc, rnames)
        obj_desc = desc_paras[0]

        genout(outfile,
               ' <tr>\n'
               '  <td class="regfn">{comp}.{link}</td>'
               '  <td class="regfn">{obj_offset:#x}</td>'
               '  <td class="regfn">{obj_length}</td>'
               '  <td class="regfn">{obj_desc}</td>'
               ' </tr>\n'
               .format(comp=comp,
                       link=get_reg_link(obj.name),
                       obj_offset=obj.offset,
                       obj_length=obj_length,
                       obj_desc=obj_desc))

    genout(outfile, '</table>')


def gen_html_register(outfile: TextIO,
                      reg: Register,
                      comp: str,
                      width: int,
                      rnames: Set[str]) -> None:
    rname = reg.name
    offset = reg.offset
    regwen_div = ''
    if reg.regwen is not None:
        regwen_div = ('    <div>Register enable = {}</div>'
                      .format(reg.regwen))

    desc_paras = expand_paras(reg.desc, rnames)
    desc_head = desc_paras[0]
    desc_body = desc_paras[1:]

    # If this is the first register of a multireg,
    # we also insert a label without the index so
    # that unnumbered links from the register table
    # descriptions and Hugo-generated docs are possible.
    if rname[-2:] == "0":
        mr_anchor = ('id="{}"'
                     .format(rname[:-2].lower()))
    else:
        mr_anchor = ''

    genout(outfile,
           '<table class="regdef" id="{lrname}">\n'
           ' <tr>\n'
           '  <th class="regdef" colspan=5 {mr_anchor}>\n'
           '   <div>{comp}.{link} @ {off:#x}</div>\n'
           '   <div>{desc}</div>\n'
           '   <div>Reset default = {resval:#x}, mask {mask:#x}</div>\n'
           '{wen}'
           '  </th>\n'
           ' </tr>\n'
           .format(mr_anchor=mr_anchor,
                   lrname=rname.lower(),
                   comp=comp,
                   link=get_reg_link(rname),
                   off=offset,
                   desc=desc_head,
                   resval=reg.resval,
                   mask=reg.resmask,
                   wen=regwen_div))
    if desc_body:
        genout(outfile,
               '<tr><td colspan=5>{}</td></tr>'
               .format(mk.markdown(desc_body)))

    genout(outfile, "<tr><td colspan=5>")
    gen_html_reg_pic(outfile, reg, width)
    genout(outfile, "</td></tr>\n")

    genout(outfile, "<tr><th width=5%>Bits</th>")
    genout(outfile, "<th width=5%>Type</th>")
    genout(outfile, "<th width=5%>Reset</th>")
    genout(outfile, "<th>Name</th>")
    genout(outfile, "<th>Description</th></tr>")
    nextbit = 0
    fcount = 0

    for field in reg.fields:
        fcount += 1
        fname = field.name

        fieldlsb = field.bits.lsb
        if fieldlsb > nextbit:
            genout(outfile, "<tr><td class=\"regbits\">")
            if (nextbit == (fieldlsb - 1)):
                genout(outfile, str(nextbit))
            else:
                genout(outfile, str(fieldlsb - 1) + ":" + str(nextbit))
            genout(outfile,
                   "</td><td></td><td></td><td></td><td>Reserved</td></tr>")
        genout(outfile, "<tr><td class=\"regbits\">" + field.bits.as_str() + "</td>")
        genout(outfile, "<td class=\"regperm\">" + field.swaccess.key + "</td>")
        genout(
            outfile, "<td class=\"regrv\">" +
            ('x' if field.resval is None else hex(field.resval)) +
            "</td>")
        genout(outfile, "<td class=\"regfn\">" + fname + "</td>")

        # Collect up any description and enum table
        desc_parts = []

        if field.desc is not None:
            desc_parts += expand_paras(mk.markdown(field.desc), rnames)

        if field.enum is not None:
            desc_parts.append('<table>')

            # Add two to include the "0x" part
            hex_width = 2 + ((field.bits.width() + 3) // 4)

            for enum in field.enum:
                enum_desc_paras = expand_paras(enum.desc, rnames)
                desc_parts.append('<tr>'
                                  '<td>{val:#0{hex_width}x}</td>'
                                  '<td>{name}</td>'
                                  '<td>{desc}</td>'
                                  '</tr>\n'
                                  .format(val=enum.value,
                                          hex_width=hex_width,
                                          name=enum.name,
                                          desc=''.join(enum_desc_paras)))
            desc_parts.append('</table>')
            if field.has_incomplete_enum():
                desc_parts.append("<p>Other values are reserved.</p>")

        genout(outfile,
               '<td class="regde">{}</td>'.format(''.join(desc_parts)))
        nextbit = fieldlsb + field.bits.width()

    genout(outfile, "</table>\n<br>\n")


def gen_window_row(outfile: TextIO,
                   base_addr: int,
                   validbits: int,
                   regwidth: int,
                   idx: Optional[int]) -> None:
    '''Generate a row for a window

    If idx is None, this is a row that shows we're skipping some addresses and
    has a "...". If idx is not None, this gives an address and we show the bits
    that are valid.
    '''
    assert 0 < validbits
    assert 0 < regwidth
    assert regwidth % 8 == 0
    assert validbits <= regwidth

    if idx is not None:
        assert idx >= 0
        addr = base_addr + idx * (regwidth // 8)
        addr_td = f'<td class="regbits">+{addr:#x}</td>'
        if validbits < regwidth:
            pad = regwidth - validbits
            unused_tds = f'<td class="unused" colspan="{pad}">&nbsp;</td>'
        else:
            unused_tds = ''
        data_tds = f'<td class="fname" colspan="{validbits}">&nbsp;</td>'
        tds = addr_td + unused_tds + data_tds
    else:
        tds = (f'<td>&nbsp;</td>'
               f'<td align="center" colspan="{regwidth}">...</td>')

    genout(outfile, f'<tr>{tds}</tr>')


def gen_html_window(outfile: TextIO,
                    win: Window,
                    comp: str,
                    regwidth: int,
                    rnames: Set[str]) -> None:
    wname = win.name or '(unnamed window)'
    offset = win.offset
    genout(outfile,
           '<table class="regdef" id="{lwname}">\n'
           '  <tr>\n'
           '    <th class="regdef">\n'
           '      <div>{comp}.{link} @ + {off:#x}</div>\n'
           '      <div>{items} item {swaccess} window</div>\n'
           '      <div>Byte writes are {byte_writes}supported</div>\n'
           '    </th>\n'
           '  </tr>\n'
           .format(comp=comp,
                   link=get_reg_link(wname),
                   lwname=wname.lower(),
                   off=offset,
                   items=win.items,
                   swaccess=win.swaccess.key,
                   byte_writes=('' if win.byte_write else '<i>not</i> ')))
    genout(outfile, '<tr><td><table class="regpic">')
    genout(outfile, '<tr><td width="10%"></td>')
    wid = win.validbits

    for x in range(regwidth - 1, -1, -1):
        if x == regwidth - 1 or x == wid - 1 or x == 0:
            genout(outfile, '<td class="bitnum">' + str(x) + '</td>')
        else:
            genout(outfile, '<td class="bitnum"></td>')
    genout(outfile, '</tr>')

    # We want to show the first and last two addresses, with a blank line in
    # between if we skip anything.
    assert win.items >= 1
    if win.items <= 4:
        indices_0 = list(range(win.items))
        indices_1 = []
    else:
        indices_0 = [0, 1]
        indices_1 = [win.items - 2, win.items - 1]

    for idx in indices_0:
        gen_window_row(outfile, offset, win.validbits, regwidth, idx)
    if indices_1:
        gen_window_row(outfile, offset, win.validbits, regwidth, None)
    for idx in indices_1:
        gen_window_row(outfile, offset, win.validbits, regwidth, idx)

    genout(outfile, '</td></tr></table>')
    genout(outfile,
           '<tr>{}</tr>'.format(render_td(win.desc, rnames, 'regde')))
    genout(outfile, "</table>\n<br>\n")


def gen_html_reg_block(outfile: TextIO,
                       rb: RegBlock,
                       comp: str,
                       width: int,
                       rnames: Set[str]) -> None:
    if len(rb.entries) == 0:
        genout(outfile, 'This interface does not expose any registers.')
    else:
        # Generate overview table first.
        obj_list: List[Union[Register, Window]] = []
        for x in rb.entries:
            if isinstance(x, MultiRegister):
                for reg in x.regs:
                    obj_list += [reg]
            else:
                assert isinstance(x, Window) or isinstance(x, Register)
                obj_list += [x]
        gen_html_register_summary(outfile, obj_list, comp, width, rnames)

        # Generate detailed entries
        for x in rb.entries:
            if isinstance(x, Register):
                gen_html_register(outfile, x, comp, width, rnames)
            elif isinstance(x, MultiRegister):
                for reg in x.regs:
                    gen_html_register(outfile, reg, comp, width, rnames)
            else:
                assert isinstance(x, Window)
                gen_html_window(outfile, x, comp, width, rnames)


def gen_html(block: IpBlock, outfile: TextIO) -> int:
    rnames = block.get_rnames()

    assert block.reg_blocks
    # Handle the case where there's just one interface
    if len(block.reg_blocks) == 1:
        rb = list(block.reg_blocks.values())[0]
        gen_html_reg_block(outfile, rb, block.name, block.regwidth, rnames)
        return 0

    # Handle the case where there is more than one device interface and,
    # correspondingly, more than one reg block.
    for iface_name, rb in block.reg_blocks.items():
        iface_desc = ('device interface <code>{}</code>'.format(iface_name)
                      if iface_name is not None
                      else 'the unnamed device interface')
        genout(outfile,
               '<h3>Registers visible under {}</h3>'.format(iface_desc))
        gen_html_reg_block(outfile, rb, block.name, block.regwidth, rnames)

    return 0
