"""Generate docs from comments."""

import os
from dataclasses import dataclass
from typing import List

# Messages --------------------------------------------------------------------

MESSAGES_DOC_TEMPLATE = """
# Full List of Messages

xplr [messages][1] categorized based on their purpose.

## Categories

{categories}

{msgs}

## Also See:

- [Message][1]

[1]: message.md
""".strip()

CONFIGURATION_DOC_TEMPLATE = """
# Configuration

{doc}

""".strip()


@dataclass
class MsgSection:
    title: str
    body: List[str]


@dataclass
class MsgCategory:
    title: str
    sections: List[MsgSection]


@dataclass
class MsgResult:
    categories: List[MsgCategory]
    msgs: List[str]


def gen_messages():
    """Generate messages.md"""

    path = "./src/msg/in_/external.rs"
    res = []
    reading = False

    with open(path) as f:
        lines = iter(f.read().splitlines())

    for line in lines:
        line = line.strip()

        if line.startswith("pub enum ExternalMsg {"):
            reading = True
            continue

        if not reading:
            continue

        if line == "}":
            break

        if line.startswith("/// ### "):
            line = line.lstrip("/// ### ").rstrip("-").strip()
            sec = MsgSection(title=None, body=[])
            cat = MsgCategory(title=line, sections=[sec])
            res.append(cat)
            continue

        if line.startswith("/// "):
            line = line.lstrip("/// ").strip()
            res[-1].sections[-1].body.append(line)
            continue

        if not line or line == "///":
            res[-1].sections[-1].body.append("")
            continue

        if line.endswith(","):
            line = line.split(",")[0].split("(")[0]
            res[-1].sections[-1].title = line

            sec = MsgSection(title=None, body=[])
            res[-1].sections.append(sec)
            continue

    result = MsgResult(categories=[], msgs=[])

    for cat in res:
        slug = cat.title.lower().replace(" ", "-")
        result.categories.append(f"- [{cat.title}](#{slug})")
        result.msgs.append(f"### {cat.title}")
        result.msgs.append("")

        for sec in cat.sections:
            if not sec.title:
                continue

            result.msgs.append(f"#### {sec.title}")
            result.msgs.append("")
            for line in sec.body:
                result.msgs.append(f"{line}")
            result.msgs.append("")

    messages = MESSAGES_DOC_TEMPLATE.format(
        categories="\n".join(result.categories), msgs="\n".join(result.msgs)
    )

    print(messages)
    with open("./docs/en/src/messages.md", "w") as f:
        print(messages, file=f)


# Configuration ---------------------------------------------------------------


def gen_configuration():
    """Generate the following docs.

    - configuration.md
    - general-config.md
    - node_types.md
    - layouts.md
    - modes.md
    - modes.md
    """

    path = "./src/init.lua"

    configuration = [[]]
    general = [[]]
    node_types = [[]]
    layouts = [[]]
    modes = [[]]

    with open(path) as f:
        lines = iter(f.read().splitlines())

    reading = None

    for line in lines:
        if line.startswith("---"):
            continue

        if (
            line.startswith("-- # Configuration ")
            or line.startswith("-- ## Config ")
            or line.startswith("-- ## Function ")
            or line.startswith("-- ## On Load ")
        ):
            reading = configuration

        if line.startswith("-- ### General Configuration "):
            reading = general

        if line.startswith("-- ### Node Types "):
            reading = node_types

        if line.startswith("-- ### Layouts "):
            reading = layouts

        if line.startswith("-- ### Modes "):
            reading = modes

        if not reading:
            continue

        if line.startswith("-- ") or line == "--":
            if line.startswith("-- #") and line.endswith("--"):
                line = "\n{0}\n".format(line.rstrip("-"))

            reading[-1].append(line[3:])
            continue

        if line.startswith("xplr.") and reading[-1]:
            reading[-1].insert(0, "\n#### {0}\n".format(line.split()[0]))
            continue

        if not line.strip() and reading[-1]:
            reading.append([])
            continue

    with open("./docs/en/src/configuration.md", "w") as f:
        doc = "\n".join(["\n".join(c) for c in configuration])
        print(doc)
        print(doc, file=f)

    with open("./docs/en/src/general-config.md", "w") as f:
        doc = "\n".join(["\n".join(c) for c in general])
        print(doc)
        print(doc, file=f)

    with open("./docs/en/src/node_types.md", "w") as f:
        doc = "\n".join(["\n".join(c) for c in node_types])
        print(doc)
        print(doc, file=f)

    with open("./docs/en/src/layouts.md", "w") as f:
        doc = "\n".join(["\n".join(c) for c in layouts])
        print(doc)
        print(doc, file=f)

    with open("./docs/en/src/modes.md", "w") as f:
        doc = "\n".join(["\n".join(c) for c in modes])
        print(doc)
        print(doc, file=f)


# xplr.util -------------------------------------------------------------------


@dataclass
class Function:
    doc: List[str]
    name: str


def gen_xplr_util():

    path = "./src/lua/util.rs"

    functions: List[Function] = []

    with open(path) as f:
        lines = iter(f.read().splitlines())

    reading = None

    for line in lines:
        if line.startswith("///"):
            if reading:
                reading.doc.append(line[4:])
            else:
                reading = Function(doc=[line[4:]], name="")

        if line.startswith("pub fn") and reading:
            reading.name = "\n### xplr.util." + line.split("<")[0].split()[-1] + "\n"
            functions.append(reading)
            reading = None
            continue

    with open("./docs/en/src/xplr.util.md", "w") as f:
        for function in functions:
            print(function.name)
            print(function.name, file=f)

            print("\n".join(function.doc))
            print("\n".join(function.doc), file=f)

        if reading:
            print("\n".join(reading.doc), file=f)


def format_docs():
    os.system("prettier --write docs/en/src")


def main():
    gen_messages()
    gen_configuration()
    gen_xplr_util()
    format_docs()


if __name__ == "__main__":
    main()
