# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html

# -- Path setup --------------------------------------------------------------

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
import os
import sys

import pybtex.style.formatting
import pybtex.style.formatting.unsrt
import pybtex.style.template
from pybtex.plugin import register_plugin as pybtex_register_plugin


sys.path.insert(0, os.path.abspath("."))
sys.path.insert(0, os.path.abspath(".."))
sys.path.insert(0, os.path.abspath("../../"))

# -- Project information -----------------------------------------------------

project = "Mitiq"
copyright = "2020, Tech Team @ Unitary Fund"
author = "Tech Team @ Unitary Fund"

# The full version, including alpha/beta/rc tags
directory_of_this_file = os.path.dirname(os.path.abspath(__file__))
with open(f"{directory_of_this_file}/../../VERSION.txt", "r") as f:
    release = f.read().strip()

sys.path.append(os.path.abspath("sphinxext"))

# -- General configuration ---------------------------------------------------

# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
    "myst_nb",
    "sphinx.ext.mathjax",
    "IPython.sphinxext.ipython_console_highlighting",
    "IPython.sphinxext.ipython_directive",
    "matplotlib.sphinxext.plot_directive",
    "sphinx.ext.napoleon",
    "sphinx.ext.autodoc",
    "sphinx.ext.autosummary",
    "sphinx_autodoc_typehints",  # after napoleon and autodoc
    "sphinx.ext.todo",
    "sphinx.ext.doctest",
    "sphinx.ext.extlinks",
    "sphinx.ext.intersphinx",
    "sphinx.ext.viewcode",
    "sphinx.ext.ifconfig",
    "sphinxcontrib.bibtex",
    "sphinx_copybutton",
    'nbsphinx',
    'sphinx_gallery.load_style'
]

intersphinx_mapping = {
    "python": ("https://docs.python.org/3.7", None),
    "numpy": ("https://numpy.org/doc/stable/", None),
    "scipy": ("https://docs.scipy.org/doc/scipy/reference/", None),
    # Cirq is no longer using sphinx docs so interlinking is not possible.
    # "cirq": ("https://quantumai.google/cirq", None),
    "pyquil": ("https://pyquil-docs.rigetti.com/en/stable/", None),
    "qiskit": ("https://qiskit.org/documentation/", None),
    "qutip": ("https://qutip.org/docs/latest/", None),
}

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

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = "en"

# 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 = [
    "guide/_guide-zne-lindblad.rst",
]

# The master toctree document.
master_doc = "index"

# -- Options for myst_parser -------------------------------------------------
# Specifies which of the parsers should handle each file extension.
source_suffix = {
    ".rst": "restructuredtext",
    ".ipynb": "myst-nb",
    ".myst": "myst-nb",
    ".mystnb": "myst-nb",
}

# Enables extensions to MyST parser that allows for richer markup options.
# For more info on these, see:
# https://myst-parser.readthedocs.io/en/latest/using/syntax-optional.html
myst_enable_extensions = [
    "amsmath",
    "colon_fence",
    "deflist",
    "dollarmath",
    "html_image",
    "smartquotes",
]

# Tells MyST to treat URIs beginning with these prefixes as external links.
# Links that don't begin with these will be treated as internal cross-links.
myst_url_schemes = ("http", "https", "mailto")

# -- Options for myst_nb -----------------------------------------------------

# Needed to explicitly set render priority for the `doctest` mode.
# https://myst-nb.readthedocs.io/en/latest/use/formatting_outputs.html#render-priority
nb_render_priority = {
    "html": (
        "application/vnd.jupyter.widget-view+json",
        "application/javascript",
        "text/html",
        "image/svg+xml",
        "image/png",
        "image/jpeg",
        "text/markdown",
        "text/latex",
        "text/plain",
    ),
    "doctest": (
        "application/vnd.jupyter.widget-view+json",
        "application/javascript",
        "text/html",
        "image/svg+xml",
        "image/png",
        "image/jpeg",
        "text/markdown",
        "text/latex",
        "text/plain",
    ),
}
# How long should Sphinx wait while a notebook is being evaluated before
# quitting.
execution_timeout = 600

# By default, if nothing has changed in the source, a notebook won't be
# re-run for a subsequent docs build.
jupyter_execute_notebooks = "cache"

# -- Options for autodoc -----------------------------------------------------
napoleon_google_docstring = True
napoleon_use_ivar = True

autodoc_mock_imports = [
    "pyquil",
]

# autodoc-typehints extension setting
typehints_fully_qualified = False
always_document_param_types = True
set_type_checking_flag = False
typehints_document_rtype = True

# -- Options for Sphinxcontrib-bibtex ----------------------------------------
pybtex.style.formatting.unsrt.date = pybtex.style.template.words(sep="")[
    "(", pybtex.style.template.field("year"), ")"
]
bibtex_bibfiles = ["refs.bib"]

# Links matching with the following regular expressions will be ignored
linkcheck_ignore = [
    r'https://doi.org/10.1088/0034-4885/74/10/104401',
    r'https://doi.org/10.1088/1367-2630/12/7/075008',
]


class ApsStyle(pybtex.style.formatting.unsrt.Style):
    """Style that mimicks APS journals."""

    def __init__(
        self,
        label_style=None,
        name_style=None,
        sorting_style=None,
        abbreviate_names=True,
        min_crossrefs=2,
        **kwargs,
    ):
        super().__init__(
            label_style=label_style,
            name_style=name_style,
            sorting_style=sorting_style,
            abbreviate_names=abbreviate_names,
            min_crossrefs=min_crossrefs,
            **kwargs,
        )

    def format_title(self, e, which_field, as_sentence=True):
        """Set titles in italics."""
        formatted_title = pybtex.style.template.field(
            which_field, apply_func=lambda text: text.capitalize()
        )
        formatted_title = pybtex.style.template.tag("em")[formatted_title]
        if as_sentence:
            return pybtex.style.template.sentence[formatted_title]
        else:
            return formatted_title

    def get_article_template(self, e):
        volume_and_pages = pybtex.style.template.first_of[
            # volume and pages
            pybtex.style.template.optional[
                pybtex.style.template.join[
                    " ",
                    pybtex.style.template.tag("strong")[
                        pybtex.style.template.field("volume")
                    ],
                    ", ",
                    pybtex.style.template.field(
                        "pages",
                        apply_func=pybtex.style.formatting.unsrt.dashify,
                    ),
                ],
            ],
            # pages only
            pybtex.style.template.words[
                "pages",
                pybtex.style.template.field(
                    "pages", apply_func=pybtex.style.formatting.unsrt.dashify
                ),
            ],
        ]
        template = pybtex.style.formatting.toplevel[
            self.format_names("author"),
            self.format_title(e, "title"),
            pybtex.style.template.sentence(sep=" ")[
                pybtex.style.template.field("journal"),
                pybtex.style.template.optional[volume_and_pages],
                pybtex.style.formatting.unsrt.date,
            ],
            self.format_web_refs(e),
        ]
        return template

    def get_book_template(self, e):
        template = pybtex.style.formatting.toplevel[
            self.format_author_or_editor(e),
            self.format_btitle(e, "title"),
            self.format_volume_and_series(e),
            pybtex.style.template.sentence(sep=" ")[
                pybtex.style.template.sentence(add_period=False)[
                    pybtex.style.template.field("publisher"),
                    pybtex.style.template.optional_field("address"),
                    self.format_edition(e),
                ],
                pybtex.style.formatting.unsrt.date,
            ],
            pybtex.style.template.optional[
                pybtex.style.template.sentence[self.format_isbn(e)]
            ],
            pybtex.style.template.sentence[
                pybtex.style.template.optional_field("note")
            ],
            self.format_web_refs(e),
        ]
        return template

    def get_incollection_template(self, e):
        template = pybtex.style.formatting.toplevel[
            pybtex.style.template.sentence[self.format_names("author")],
            self.format_title(e, "title"),
            pybtex.style.template.words[
                "In",
                pybtex.style.template.sentence[
                    pybtex.style.template.optional[
                        self.format_editor(e, as_sentence=False)
                    ],
                    self.format_btitle(e, "booktitle", as_sentence=False),
                    self.format_volume_and_series(e, as_sentence=False),
                    self.format_chapter_and_pages(e),
                ],
            ],
            pybtex.style.template.sentence(sep=" ")[
                pybtex.style.template.sentence(add_period=False)[
                    pybtex.style.template.optional_field("publisher"),
                    pybtex.style.template.optional_field("address"),
                    self.format_edition(e),
                ],
                pybtex.style.formatting.unsrt.date,
            ],
            self.format_web_refs(e),
        ]
        return template


pybtex_register_plugin("pybtex.style.formatting", "apsstyle", ApsStyle)

# -- Options for other extensions --------------------------------------------
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = "sphinx"

# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False

# -- Options for HTML output -------------------------------------------------

# The theme to use for HTML and HTML Help pages.  See the documentation for
# a list of builtin themes.
#
html_theme = "pydata_sphinx_theme"  # 'alabaster', 'sphinx_rtd_theme'

# 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']

# display logo on top-left of html pages
html_logo = "img/mitiq-logo.png"

myst_update_mathjax = False

nbsphinx_custom_formats = {
    '.mystnb': ['jupytext.reads', {'fmt': 'mystnb'}],
}
nbsphinx_execute = 'always'

nbsphinx_thumbnails = {
    'examples/hamiltonians': '_images/vqe-cirq-pauli-sum-mitigation-plot.png',
    'examples/simple_landscape': '_images/simple_landscape_13_0.png',
    'examples/maxcut-demo': '_images/maxcut-demo_48_1.png',
    'examples/pyquil-demo': '_images/pyquil_demo_11_0.png',
    'examples/pec-tutorial': '_images/pec-tutorial_62_0.png',
    # default images if no thumbnail is specified
    'examples/*': '_static/mitiq-logo.png',
    'examples/mitiq-paper/*': '_static/mitiq-logo.png'
}
