# 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 Block
"""

from typing import TextIO

from reggen.ip_block import IpBlock
from reggen.html_helpers import render_td
from reggen.signal import Signal


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


def name_width(x: Signal) -> str:
    if x.bits.width() == 1:
        return x.name

    return '{}[{}:0]'.format(x.name, x.bits.msb)


def gen_kv(outfile: TextIO, key: str, value: str) -> None:
    genout(outfile,
           '<p><i>{}:</i> {}</p>\n'.format(key, value))


def gen_cfg_html(cfgs: IpBlock, outfile: TextIO) -> None:
    rnames = cfgs.get_rnames()

    ot_server = 'https://docs.opentitan.org'
    comport_url = ot_server + '/doc/rm/comportability_specification'
    genout(outfile,
           '<p>Referring to the <a href="{url}">Comportable guideline for '
           'peripheral device functionality</a>, the module '
           '<b><code>{mod_name}</code></b> has the following hardware '
           'interfaces defined.</p>\n'
           .format(url=comport_url, mod_name=cfgs.name))

    # clocks
    gen_kv(outfile,
           'Primary Clock',
           '<b><code>{}</code></b>'.format(cfgs.clocking.primary.clock))
    other_clocks = cfgs.clocking.other_clocks()
    if other_clocks:
        other_clocks_str = ['<b><code>{}</code></b>'.format(clk)
                            for clk in other_clocks]
        gen_kv(outfile, 'Other Clocks', ', '.join(other_clocks_str))
    else:
        gen_kv(outfile, 'Other Clocks', '<i>none</i>')

    # bus interfaces
    dev_ports = ['<b><code>{}</code></b>'.format(port)
                 for port in cfgs.bus_interfaces.get_port_names(False, True)]
    assert dev_ports
    gen_kv(outfile, 'Bus Device Interfaces (TL-UL)', ', '.join(dev_ports))

    host_ports = ['<b><code>{}</code></b>'.format(port)
                  for port in cfgs.bus_interfaces.get_port_names(True, False)]
    if host_ports:
        gen_kv(outfile, 'Bus Host Interfaces (TL-UL)', ', '.join(host_ports))
    else:
        gen_kv(outfile, 'Bus Host Interfaces (TL-UL)', '<i>none</i>')

    # IO
    ios = ([('input', x) for x in cfgs.xputs[1]] +
           [('output', x) for x in cfgs.xputs[2]] +
           [('inout', x) for x in cfgs.xputs[0]])
    if ios:
        genout(outfile, "<p><i>Peripheral Pins for Chip IO:</i></p>\n")
        genout(
            outfile, "<table class=\"cfgtable\"><tr>" +
            "<th>Pin name</th><th>direction</th>" +
            "<th>Description</th></tr>\n")
        for direction, x in ios:
            genout(outfile,
                   '<tr><td>{}</td><td>{}</td>{}</tr>'
                   .format(name_width(x),
                           direction,
                           render_td(x.desc, rnames, None)))
        genout(outfile, "</table>\n")
    else:
        genout(outfile, "<p><i>Peripheral Pins for Chip IO: none</i></p>\n")

    # Inter-Module Signals
    if not cfgs.inter_signals:
        genout(outfile, "<p><em>Inter-Module Signals: none</em></p>\n")
    else:
        genout(outfile,
               "<p><em>Inter-Module Signals:</em>\n" +
               "<a href=\"/doc/rm/comportability_specification/#inter-signal-handling\">\n" +
               "Reference</a></p>\n")

        genout(outfile,
               "<table class=\"cfgtable\">\n" +
               "  <caption>Inter-Module Signals</caption>\n" +
               "  <thead>\n" +
               "    <tr>\n" +
               "      <th>Port Name</th>\n" +
               "      <th>Package::Struct</th>\n" +
               "      <th>Type</th>\n" +
               "      <th>Act</th>\n" +
               "      <th>Width</th>\n" +
               "      <th>Description</th>\n" +
               "    </tr>\n" +
               "  </thead>\n" +
               "  <tbody>\n")

        for ims in cfgs.inter_signals:
            name = ims.name
            pkg_struct = ims.package + "::" + ims.struct if ims.package is not None else ims.struct
            sig_type = ims.signal_type
            act = ims.act
            width = str(ims.width) if ims.width is not None else "1"
            desc = ims.desc if ims.desc is not None else ""
            genout(outfile,
                   "    <tr>\n" +
                   "      <td>" + name + "</td>\n" +
                   "      <td>" + pkg_struct + "</td>\n" +
                   "      <td>" + sig_type + "</td>\n" +
                   "      <td>" + act + "</td>\n" +
                   "      <td>" + width + "</td>\n" +
                   "      <td>" + desc + "</td>\n" +
                   "    </tr>\n")
            continue

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

    if not cfgs.interrupts:
        genout(outfile, "<p><i>Interrupts: none</i></p>\n")
    else:
        genout(outfile, "<p><i>Interrupts:</i></p>\n")
        genout(
            outfile, "<table class=\"cfgtable\"><tr><th>Interrupt Name</th>" +
            "<th>Type</th><th>Description</th></tr>\n")
        for x in cfgs.interrupts:
            genout(outfile,
                   '<tr><td>{}</td><td>{}</td>{}</tr>'
                   .format(name_width(x),
                           x.intr_type.name,
                           render_td(x.desc, rnames, None)))
        genout(outfile, "</table>\n")

    if not cfgs.alerts:
        genout(outfile, "<p><i>Security Alerts: none</i></p>\n")
    else:
        genout(outfile, "<p><i>Security Alerts:</i></p>\n")
        genout(
            outfile, "<table class=\"cfgtable\"><tr><th>Alert Name</th>" +
            "<th>Description</th></tr>\n")
        for x in cfgs.alerts:
            genout(outfile,
                   '<tr><td>{}</td>{}</tr>'
                   .format(x.name,
                           render_td(x.desc, rnames, None)))
        genout(outfile, "</table>\n")

    if not cfgs.countermeasures:
        genout(outfile, "<p><i>Security Countermeasures: none</i></p>\n")
    else:
        genout(outfile, "<p><i>Security Countermeasures:</i></p>\n")
        genout(
            outfile, "<table class=\"cfgtable\"><tr><th>Countermeasure ID</th>" +
            "<th>Description</th></tr>\n")
        for cm in cfgs.countermeasures:
            genout(outfile,
                   '<tr><td>{}</td>{}</tr>'
                   .format(cfgs.name.upper() + '.' + str(cm),
                           render_td(cm.desc, rnames, None)))
        genout(outfile, "</table>\n")
