#!/usr/bin/env python

# To run this script, first make webdocs in the toplevel of the checkout.
# This will generate all rst files from their sources.
# Then run this script ./docs/bin/find-plugin-refs.py
#
# No output means that there are no longer any bare module and plugin names
# referenced via :ref:
#
# For my listing of what needs to be changed after running this script,
# see the comment at the end of the file

from __future__ import annotations

import glob
import os
import re
from collections.abc import Collection

TOPDIR = os.path.join(os.path.dirname(__file__), "..", "docsite", "rst")


def plugin_names(topdir: str | os.PathLike[str]):
    plugins = set()

    # Modules are in a separate directory
    for module_filename in glob.glob(os.path.join(topdir, "modules", "*_module.rst")):
        module_filename = os.path.basename(module_filename)
        module_name = module_filename[: module_filename.index("_module.rst")]
        plugins.add(module_name)

    for plugin_filename in glob.glob(os.path.join(topdir, "plugins", "*", "*.rst")):
        plugin_filename = os.path.basename(plugin_filename)
        plugin_name = plugin_filename[: plugin_filename.index(".rst")]
        plugins.add(plugin_name)

    return plugins


def process_refs(topdir: str | os.PathLike[str], plugin_names: Collection[str]):
    REF_RE = re.compile(":ref:`([^`]*)`")
    LABEL_RE = re.compile("<([^>]*)>$")

    # Walk the whole docs tree looking for :ref:.
    # Anywhere those are found, search for `([^`]*)`
    for dirpath, dirnames, filenames in os.walk(topdir):
        for filename in filenames:
            with open(os.path.join(dirpath, filename), "r") as f:
                data = f.read()
                for ref_match in re.finditer(REF_RE, data):
                    label = ref_match.group(1)

                    # If the ref label includes "<", then search for the label
                    # inside of the "<>"
                    label_match = re.search(LABEL_RE, label)
                    if label_match:
                        label = label_match.group(1)

                    # If the ref label is listed in plugins, then print that
                    # the file contains an unported ref
                    if label in plugin_names:
                        print(
                            ":ref:`{0}` matching plugin {1} was found in {2}".format(
                                ref_match.group(1),
                                label,
                                os.path.join(dirpath, filename),
                            )
                        )


if __name__ == "__main__":
    plugins = plugin_names(TOPDIR)

    process_refs(TOPDIR, plugins)

    # Fixes needed: docs/bin/plugin_formatter.py
    # - t = _MODULE.sub(r":ref:`\1 <\1>`", t)
    # + t = _MODULE.sub(r":ref:`\1 <module_\1>`", t)
    #
    # These have @{module}@ in the template and need to have something like
    # module_@{module}@
    # If any of these list plugins as well as modules,
    # they will need to have a conditional or extra data passed in to handle
    # that in a generic fashion:
    #
    # docs/templates/list_of_CATEGORY_modules.rst.j2
    # docs/templates/list_of_CATEGORY_plugins.rst.j2
    # docs/templates/modules_by_support.rst.j2
    #
    # These are just a simple manual fix:
    # :ref:`command` matching plugin command was found in
    # ./../docsite/rst/user_guide/intro_adhoc.rst
    #
    # :ref:`shell` matching plugin shell was found in
    # ./../docsite/rst/user_guide/intro_adhoc.rst
    #
    # :ref:`config` matching plugin config was found in
    # ./../docsite/rst/installation_guide/intro_configuration.rst
