#!/usr/bin/python3
# -*- mode: python; coding: utf-8; eval: (blacken-mode); -*-
"""
Convert Doxygen HTML documentation for a PipeWire module to RST.
"""
import argparse
import html, html.parser
import re
from pathlib import Path
from subprocess import check_output
TEMPLATE = """
{name}
{name_underline}
{subtitle_underline}
{subtitle}
{subtitle_underline}
:Manual section: 7
:Manual group: PipeWire
DESCRIPTION
-----------
{content}
AUTHORS
-------
The PipeWire Developers <{PACKAGE_BUGREPORT}>;
PipeWire is available from {PACKAGE_URL}
SEE ALSO
--------
{seealso}
"""
def main():
    p = argparse.ArgumentParser(description=__doc__.strip())
    p.add_argument(
        "-D",
        "--define",
        nargs=2,
        action="append",
        dest="define",
        default=[],
    )
    p.add_argument("pandoc")
    p.add_argument("module")
    p.add_argument("htmldir", type=Path)
    args = p.parse_args()
    page = args.module.lower().replace("-", "_")
    src = args.htmldir / f"page_{page}.html"
    # Pick content block only
    parser = DoxyParser()
    with open(src, "r") as f:
        parser.feed(f.read())
    data = "".join(parser.content)
    # Produce output
    content = check_output(
        [args.pandoc, "-f", "html", "-t", "rst"], input=data, encoding="utf-8"
    )
    if not content.strip() or content.lower().startswith("module name\n-----"):
        content = "Undocumented.\n\n" + content
    if args.module.startswith("pulse-"):
        name = re.sub(r"^pulse-module-", "module-", args.module)
        seealso = "``pipewire-pulse(1)``, ``pipewire-pulse-modules(7)``"
        subtitle = "PipeWire Pulseaudio module"
    else:
        name = f"libpipewire-{args.module}"
        seealso = "``pipewire(1)``, ``pipewire.conf(5)``, ``libpipewire-modules(7)``"
        subtitle = "PipeWire module"
    env = dict(
        content=content,
        name=name,
        name_underline="#" * len(name),
        subtitle=subtitle,
        subtitle_underline="-" * len(subtitle),
        seealso=seealso,
    )
    for k, v in args.define:
        env[k] = v
    print(TEMPLATE.format(**env))
def replace_pw_key(key):
    key = key.lower().replace("_", ".")
    if key in ("protocol", "access", "client.access") or key.startswith("sec."):
        return f"pipewire.{key}"
    return key
class DoxyParser(html.parser.HTMLParser):
    """
    Capture div.textblock, and:
    - Convert div.fragment to pre
    - Convert a[@href="page_module_XXX.html"] to libpipewire-module-xxx(7)
    """
    def __init__(self):
        super().__init__()
        self.content = []
        self.stack = []
    def feed(self, data):
        try:
            super().feed(data)
        except EOFError:
            pass
    def handle_starttag(self, tag, attrs):
        attrs = dict(attrs)
        if self.stack:
            if self.stack[-1] is None:
                self.stack.append(None)
                return
            if tag == "div" and attrs.get("class") == "fragment":
                tag = "pre"
                attrs = dict()
            elif tag == "a" and attrs.get("href").startswith("page_module_"):
                module = attrs["href"].replace("page_module_", "libpipewire-module-")
                module = module.replace(".html", "").replace("_", "-")
                self.content.append(f"{module}(7)")
                self.stack.append(None)
                return
            attrstr = " ".join(f'{k}="{html.escape(v)}"' for k, v in attrs.items())
            self.content.append(f"<{tag} {attrstr}>")
            self.stack.append(tag)
        elif tag == "div" and attrs.get("class") == "textblock":
            self.stack.append(tag)
    def handle_endtag(self, tag):
        if len(self.stack) == 1:
            raise EOFError()
        elif self.stack:
            otag = self.stack.pop()
            if otag is not None:
                self.content.append(f"{otag}>")
    def handle_data(self, data):
        if self.stack and self.stack[-1] is not None:
            if self.stack[-1] == "a":
                m = re.match(r"^(PW|SPA)_KEY_([A-Z_]+)$", data)
                if m:
                    data = replace_pw_key(m.group(2))
            self.content.append(html.escape(data))
if __name__ == "__main__":
    main()