from importlib import import_module
from pathlib import Path
from textwrap import dedent, indent

# Auto-generation disclaimer text
HEADER = dedent(
    """
    ..
      This file was automatically generated by docs/generate_rst_api.py. The

          make docs-rst-api

      target automates this process.
    """
).strip()


def write_if_modified(filename, content):
    filename.parent.mkdir(parents=True, exist_ok=True)

    try:
        with open(filename, "r") as f:
            existing = f.read()
    except OSError:
        existing = None

    if existing == content:
        print(f"Skipping unchanged '{filename.name}'")

    else:
        print(f"Generating '{filename.name}'")
        with open(filename, "w") as f:
            f.write(content)


# List of (module, variable) pairs
FACTORIES = [
    ("eradiate.radprops", "rad_profile_factory"),
    ("eradiate.scenes.atmosphere", "atmosphere_factory"),
    ("eradiate.scenes.atmosphere", "particle_distribution_factory"),
    ("eradiate.scenes.biosphere", "biosphere_factory"),
    ("eradiate.scenes.bsdfs", "bsdf_factory"),
    ("eradiate.scenes.illumination", "illumination_factory"),
    ("eradiate.scenes.integrators", "integrator_factory"),
    ("eradiate.scenes.measure", "measure_factory"),
    ("eradiate.scenes.phase", "phase_function_factory"),
    ("eradiate.scenes.shapes", "shape_factory"),
    ("eradiate.scenes.spectra", "spectrum_factory"),
    ("eradiate.scenes.surface", "surface_factory"),
]


def factory_data_docs(modname, varname, uline="="):
    """
    Return rst code for a factory instance located at modname.varname.
    """
    factory = getattr(import_module(modname), varname)
    fullname = f"{modname}.{varname}"
    underline = uline * len(fullname)

    table_header = ".. list-table::\n   :widths: 25 75"
    table_rows = "\n".join(
        [
            f"   * - ``{key}``\n     - :class:`{factory.get_type(key).__name__}`"
            for key in sorted(factory.registry.keys())
        ]
    )
    table = "\n".join([table_header, "", table_rows])

    return f"""{fullname}
{underline}

.. data:: {modname}.{varname}
   :annotation:

   Instance of :class:`{factory.__class__.__module__}.{factory.__class__.__qualname__}`

   .. rubric:: Registered types

{indent(table, "   ")}

""".lstrip()


def generate_factory_docs():
    """
    Generate rst documents to display factory documentation.
    """
    outdir = Path(__file__).parent.absolute() / "rst/reference_api/generated/factory"
    print(f"Generating factory docs in '{outdir}'")

    for modname, varname in FACTORIES:
        generated = factory_data_docs(modname, varname)
        content = "\n".join([HEADER, "", generated, ""])
        write_if_modified(outdir / f"{modname}.{varname}.rst", content)


if __name__ == "__main__":
    generate_factory_docs()
