#!/usr/bin/env python
#
# ====- Generate documentation for libc functions  ------------*- python -*--==#
#
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
# ==-------------------------------------------------------------------------==#
from argparse import ArgumentParser, Namespace
from pathlib import Path
from typing import Dict
import os
import sys
import yaml

from header import Header


class DocgenAPIFormatError(Exception):
    """Raised on fatal formatting errors with a description of a formatting error"""


def check_api(header: Header, api: Dict):
    """
    Checks that docgen yaml files are properly formatted. If there are any
    fatal formatting errors, raises exceptions with error messages useful for
    fixing formatting. Warnings are printed to stderr on non-fatal formatting
    errors. The code that runs after ``check_api(api)`` is called expects that
    ``check_api`` executed without raising formatting exceptions so the yaml
    matches the formatting specified here.

    The yaml file may contain:
    * an optional macros object
    * an optional functions object

    Formatting of ``macros`` and ``functions`` objects
    ==================================================

    If a macros or functions object is present, then it may contain nested
    objects. Each of these nested objects should have a name matching a macro
    or function's name, and each nested object must have the property:
    ``"c-definition"`` or ``"posix-definition"``.

    Description of properties
    =========================
    The defined property is intended to be a reference to a part of the
    standard that defines the function or macro. For the ``"c-definition"`` property,
    this should be a C standard section number. For the ``"posix-definition"`` property,
    this should be a link to the definition.

    :param api: docgen yaml file contents parsed into a dict
    """
    errors = []
    # We require entries to have at least one of these.
    possible_keys = [
        "c-definition",
        "in-latest-posix",
        "removed-in-posix-2008",
        "removed-in-posix-2024",
    ]

    # Validate macros
    if "macros" in api:
        if not header.macro_file_exists():
            print(
                f"warning: Macro definitions are listed for {header.name}, but no macro file can be found in the directory tree rooted at {header.macros_dir}. All macros will be listed as not implemented.",
                file=sys.stderr,
            )

        macros = api["macros"]

        for name, obj in macros.items():
            if not any(k in obj for k in possible_keys):
                err = f"error: Macro {name} does not contain at least one required property: {possible_keys}"
                errors.append(err)

    # Validate functions
    if "functions" in api:
        if not header.fns_dir_exists():
            print(
                f"warning: Function definitions are listed for {header.name}, but no function implementation directory exists at {header.fns_dir}. All functions will be listed as not implemented.",
                file=sys.stderr,
            )

        fns = api["functions"]
        for name, obj in fns.items():
            if not any(k in obj for k in possible_keys):
                err = f"error: function {name} does not contain at least one required property: {possible_keys}"
                errors.append(err)

    if errors:
        raise DocgenAPIFormatError("\n".join(errors))


def load_api(header: Header) -> Dict:
    api = header.docgen_yaml.read_text(encoding="utf-8")
    return yaml.safe_load(api)


def print_tbl_dir(name):
    print(
        f"""
.. list-table::
  :widths: auto
  :align: center
  :header-rows: 1

  * - {name}
    - Implemented
    - C23 Standard Section
    - POSIX Docs"""
    )


def print_functions_rst(header: Header, functions: Dict):
    tbl_hdr = "Functions"
    print(tbl_hdr)
    print("=" * len(tbl_hdr))

    print_tbl_dir("Function")

    for name in sorted(functions.keys()):
        print(f"  * - {name}")

        if header.fns_dir_exists() and header.implements_fn(name):
            print("    - |check|")
        else:
            print("    -")

        if "c-definition" in functions[name]:
            print(f'    - {functions[name]["c-definition"]}')
        else:
            print("    -")

        if "in-latest-posix" in functions[name]:
            print(
                f"    - `POSIX.1-2024 <https://pubs.opengroup.org/onlinepubs/9799919799/functions/{name}.html>`__"
            )
        elif "removed-in-posix-2008" in functions[name]:
            print(
                f"    - `removed in POSIX.1-2008 <https://pubs.opengroup.org/onlinepubs/007904875/functions/{name}.html>`__"
            )
        elif "removed-in-posix-2024" in functions[name]:
            print(
                f"    - `removed in POSIX.1-2024 <https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/functions/{name}.html>`__"
            )
        else:
            print("    -")


def print_macros_rst(header: Header, macros: Dict):
    tbl_hdr = "Macros"
    print(tbl_hdr)
    print("=" * len(tbl_hdr))

    print_tbl_dir("Macro")

    for name in sorted(macros.keys()):
        print(f"  * - {name}")

        if header.macro_file_exists() and header.implements_macro(name):
            print("    - |check|")
        else:
            print("    -")

        if "c-definition" in macros[name]:
            print(f'    - {macros[name]["c-definition"]}')
        else:
            print("    -")

        if "in-latest-posix" in macros[name]:
            print(
                f"    - `POSIX.1-2024 <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/{header.name}.html>`__"
            )
        else:
            print("    -")
    print()


def print_impl_status_rst(header: Header, api: Dict):
    if os.sep in header.name:
        print(".. include:: ../../check.rst\n")
    else:
        print(".. include:: ../check.rst\n")

    print("=" * len(header.name))
    print(header.name)
    print("=" * len(header.name))
    print()

    # the macro and function sections are both optional
    if "macros" in api:
        print_macros_rst(header, api["macros"])

    if "functions" in api:
        print_functions_rst(header, api["functions"])


# This code implicitly relies on docgen.py being in the same dir as the yaml
# files and is likely to need to be fixed when re-integrating docgen into
# hdrgen.
def get_choices() -> list:
    choices = []
    for path in Path(__file__).parent.rglob("*.yaml"):
        fname = path.with_suffix(".h").name
        if path.parent != Path(__file__).parent:
            fname = path.parent.name + os.sep + fname
        choices.append(fname)
    return choices


def parse_args() -> Namespace:
    parser = ArgumentParser()
    parser.add_argument("header_name", choices=get_choices())
    return parser.parse_args()


if __name__ == "__main__":
    args = parse_args()
    header = Header(args.header_name)
    api = load_api(header)
    check_api(header, api)

    print_impl_status_rst(header, api)
