# Configuration file for the Sphinx documentation builder.
# https://www.sphinx-doc.org/en/master/usage/configuration.html

# -- Imports -----------------------------------------------------------------
import os
from datetime import datetime
from importlib.metadata import version as metadata_version, metadata
from pathlib import Path
import json

from sphinx.util import logging
logger = logging.getLogger(__name__)

needs_sphinx = '6.1'

# -- Automatic Information ---------------------------------------------------
now = datetime.now()
year = '%d' % now.year

# `production`/`debug` tags
# - Can be used on the document as:
#   .. only:: production
#   .. only:: debug
# - Defaults to debug mode
PRODUCTION = tags.has('production')  # noqa: F821
if not PRODUCTION:
    tags.add('debug')  # noqa: F821

# Tk Version
try:
    import tkinter as tk
    tk_version = tk._tkinter.TK_VERSION
except ImportError:
    tk_version = ''

# -- Project information -----------------------------------------------------
project = os.environ.get('READTHEDOCS_PROJECT', os.environ['PROJECT'])
metadata_project = metadata(project)
author = metadata_project.get('Author', 'Powertools Technologies')
copyright = f'{year}, {author}'

category = 'Miscellaneous'
description = metadata_project.get('Summary', f'{project} Description')

version = metadata_version(project)
release = version if PRODUCTION else 'dev'

# Primary Project Domain
# https://www.sphinx-doc.org/en/master/usage/restructuredtext/domains.html
primary_domain = 'py'

# The language for content autogenerated by Sphinx, and for marking the docs.
# https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language
# See Also: https://www.sphinx-doc.org/en/master/usage/advanced/intl.html#intl
# language = None # This is given in `SPHINX_LANGUAGE` on the `Makefile`

# -- Project Settings --------------------------------------------------------

# The suffix(es) of source filenames.
source_suffix = {
    '.rst': 'restructuredtext',
    # '.md': 'markdown',
}

# The master toctree document.
root_doc = 'index'

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = [
    'Thumbs.db',
    '.DS_Store',
]

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']

# Show warnings on the built docs. Useful for debugging
keep_warnings = PRODUCTION is False
# List of warnings to suppress
suppress_warnings = [
]


# Default role
# `txt` is equivalent to :DEFAULT_ROLE:``
default_role = 'any'

today_fmt = '%d %B %Y'

# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'

# Default highlight language
highlight_language = 'none'

# Automatically number figures (with caption)
numfig = True

# -- Sphinx Extensions ----------------------------------------------------

extensions = []

# InterSphinx
# Link to other Sphinx documentation repositories
extensions.append('sphinx.ext.intersphinx')
# - See `release/docs-intersphinx.py` for this setup
intersphinx_cache_folder = Path('_inventories')
intersphinx_cache_metadata_fname = intersphinx_cache_folder / 'metadata.json'
if intersphinx_cache_metadata_fname.is_file():
    logger.info('load intersphinx metadata from %s...', intersphinx_cache_metadata_fname)
    with intersphinx_cache_metadata_fname.open('r') as fobj:
        intersphinx_cache_metadata = json.load(fobj)
else:
    intersphinx_cache_metadata = {
    }
# Defined in `release/docs-intersphinx.py`, on the "MAPPING" variable
intersphinx_mapping = {
    key: (
        url,
        (str(intersphinx_cache_folder / f'{key}.inv'), None),
    )
    for key, url in intersphinx_cache_metadata.items()
}
intersphinx_cache_limit = -1  # Forever
intersphinx_timeout = 5  # seconds

# MathJAX - https://docs.mathjax.org/en/latest/installation.html#installation
# By default uses the CDN AKA an external server.
# See the installation URL for a local install, but it's big (>30MB)
#  extension.append('sphinx.ext.mathjax')

# GraphViz
# Use SVG instead of rendering to PNG
extensions.append('sphinx.ext.graphviz')
graphviz_output_format = 'svg'

# Automatically Label Sections
# Add a reference to all document sections.
# https://www.sphinx-doc.org/en/master/usage/extensions/autosectionlabel.html
extensions.append('sphinx.ext.autosectionlabel')
autosectionlabel_prefix_document = True  # Prefix reference with document name

# AutoDoc
extensions.append('sphinx.ext.autodoc')
autodoc_member_order = 'groupwise'
autodoc_default_options = {
    'members': True,
    'show-inheritance': True,
}
autodoc_typehints = 'both'
autodoc_typehints_description_target = 'documented'

# AutoDoc: Napoleon
# Convert Google-style docstring to proper rst metadata
extensions.append('sphinx.ext.napoleon')
napoleon_google_docstring = True
napoleon_numpy_docstring = False
napoleon_use_admonition_for_examples = True
napoleon_use_admonition_for_notes = True
napoleon_use_admonition_for_references = True
napoleon_attr_annotations = True

# AutoSummary
extensions.append('sphinx.ext.autosummary')
autosummary_generate = True
autosummary_generate_overwrite = False

# Auto API Documentation
# - A souped-up version of AutoSummary and AutoDoc
extensions.append('sphinx_automodapi.automodapi')
extensions.append('sphinx_automodapi.smart_resolver')

# Expose slow files
# - Only in production
if PRODUCTION:
    extensions.append('sphinx.ext.duration')

# Support ToDo
extensions.append('sphinx.ext.todo')
todo_emit_warnings = PRODUCTION is False
todo_include_todos = PRODUCTION is False

# Shorten External Links
extensions.append('sphinx.ext.extlinks')
extlinks = {
    # lpformat: Local Project in another Format, current location.
    #           Technically not an "external" link.
    #           The argument is the file extension. Usually only "pdf" is available.
    #           Usage:
    #             :lformat:`here <pdf>`
    #             :lformat:`pdf`
    'lpformat': (f'{project}.%s', 'Format[%s]'),
    # Tcl: TclCmd online manpages, for the correct version
    'tcl': (f'https://tcl.tk/man/tcl{tk_version}/TclCmd/%s', '``Tcl`` %s'),
    # TclTk: TkCmd online manpages, for the correct version
    'tk': (f'https://tcl.tk/man/tcl{tk_version}/TkCmd/%s', '``Tk`` %s'),
    # TclTk Library: TkLib online manpages, for the correct version
    'tk_lib': (f'https://tcl.tk/man/tcl{tk_version}/TkLib/%s', '``Tk`` %s'),
    # effbot: An Introduction to Tkinter by Fredrik Lundh
    'tkinter_effbot': ('https://effbot.org/tkinterbook/%s', '``effbot`` %s'),
    # NMT Computer Center tkinter8.5 reference guide
    # - Original URL: http://www.nmt.edu/tcc/help/pubs/tkinter/web/index.html
    # - Wayback Machine: https://web.archive.org/web/20171129043813/http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/%s
    #   - Do not use, no images
    'tkinter_nmt': ('https://anzeljg.github.io/rin2/book2/2405/docs/tkinter/%s', 'NMT %s'),
}
extlinks_detect_hardcoded_links = True  # Check hardcoded links that can use `extlinks`

# See Also:
# # extensions.append('sphinx.ext.ifconfig')
# # extensions.append('sphinx.ext.doctest')
# https://github.com/wpilibsuite/sphinxext-opengraph
# https://github.com/executablebooks/sphinx-autobuild#readme
# https://github.com/executablebooks/sphinx-copybutton#readme

# Optional:
# Include GitHub Pages Detritus
extensions.append('sphinx.ext.githubpages')

# -- Options for HTML output -------------------------------------------------
html_theme = 'furo'

# Theme: Alabaster (default)
# https://alabaster.readthedocs.io/en/latest/customization.html#theme-options
if html_theme == 'alabaster':
    pass

# Theme: Read the Docs
# https://sphinx-rtd-theme.readthedocs.io/en/stable/configuring.html#theme-options
if html_theme == 'sphinx_rtd_theme':
    html_theme_options = {
        'collapse_navigation': False,
        'navigation_depth': '-1',
        'display_version': True,
        'logo_only': False,
        'prev_next_buttons_location': None,
        'style_external_links': True,
        # 'style_nav_header_background': None,
    }

# Theme: furo
# https://pradyunsg.me/furo/
if html_theme == 'furo':
    html_theme_options = {
        'light_css_variables': {
            'color-brand-primary': '#FF6600',
            'color-brand-content': '#FF6600',
        },
        'dark_css_variables': {
            'color-brand-primary': '#FF6600',
            'color-brand-content': '#FF6600',
        },
    }
    navigation_with_keys = True
    pygments_dark_style = 'monokai'

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']

# Don't include the source files in the HTML output
html_copy_source = False

# Use this favicon for the HTML documents.
# Relative to the documentation folder, `../` is the repository root.
# https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-html_favicon
html_favicon = '../release/icon.ico'

# Base URL locations. To be filled at runtime, based on `$BASEURL`
html_baseurl = os.environ.get('BASEURL', '')
html_use_opensearch = html_baseurl

# https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-manpages_url
manpages_url = 'https://man.archlinux.org/man/{page}.{section}'

# -- Options for LaTeX output ---------------------------------------------

# One entry per LaTeX file. List of tuple:
# (source start file, target name, title, author, documentclass [howto, manual, or own class], toctree_only)
latex_documents = [
    # "Main" document, section 7: Miscellaneous
    (root_doc, '%s.tex' % project, '%s' % project, author, 'manual', False),
]

latex_engine = 'xelatex'
latex_logo = '_images/logo_horizontal.png'  # Show on the top of the title page. `None` to disable.
latex_toplevel_sectioning = 'part'
latex_domain_indices = True  # Generate domain indexes
latex_show_pagerefs = True  # Show page references on PDF
latex_show_urls = 'footnote'  # Show URL as footnotes
latex_use_xindy = True  # Use `xindy` instead of `makeindex`
latex_additional_files = [
    'sphinx.sty',  # Default Sphinx Package
    'custom.sty',
]

latex_elements = {
    'papersize': 'a4paper',  # A4 paper
    'pointsize': '12pt',  # Body font size
    'passoptionstopackages': r'\PassOptionsToPackage{svgnames}{xcolor}',
    'fncychap': r'',  # No default fancy headers
    'releasename': 'Release',
    'printindex': '',  # No final index
    'preamble': r'''
    \usepackage{custom}
    ''',
}

# -- Options for manual page output ---------------------------------------

# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
    # "Main" manual page, section 7: Miscellaneous
    (root_doc, project, '%s Documentation' % project, [author], 7)
]
manpage_folder = Path('manpage')
if manpage_folder.is_dir():
    for fpath in manpage_folder.glob('*.rst'):
        fbase = fpath.stem
        man_description = None
        fdesc = fpath.with_suffix('.desc')
        if fdesc.is_file():
            with fdesc.open('r') as f:
                man_description = next(f)  # Use only the first line
        if not isinstance(man_description, str):  # Fallback description
            man_description = '%s Manual' % fbase
        logger.info('[standalone manpage] create "%s"', fbase)
        man_pages.append((str(manpage_folder / fbase), str(fbase), man_description, [author], 1))

# Add URL addresses after links
man_show_urls = True

# Create the MANPATH structure
man_make_section_directory = True

# Allow for `{}` to control emphasis. Example: `.. option:: -c <{FILE}>`
# https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-option_emphasise_placeholders
option_emphasise_placeholders = True

# -- Options for Texinfo output -------------------------------------------

# One entry per texinfo document. List of tuples
# (source start file, target name, title, author, dir menu entry, description, category, toctree_only)
texinfo_documents = [
    # "Main" texinfo page, category: Miscellaneous
    (root_doc, project, '%s Documentation' % project, '@*'.join([author]), project, description, 'Miscellaneous', False),
]

texinfo_show_urls = 'footnote'  # Show URL as footnotes
texinfo_no_detailmenu = False  # Generate detailed menu on "Top"
texinfo_cross_references = True  # Generate cross references

# -- Options for linkcheck ------------------------------------------------

# Regexes with ignored URL
linkcheck_ignore = [
    # NMT Computer Center tkinter8.5 reference guide
    # - This page is now offline
    'http://www.nmt.edu/tcc/help/pubs/tkinter/web/index.html',
]

# Map URL regex to headers to be sent
linkcheck_request_headers = {
    "*": {
        "Accept": "text/html,application/xhtml+xml",
    }
}

# Check `#anchors` in URL, by parsing the result
linkcheck_anchors = True

linkcheck_retries = 5
