# -----------------------------------------------------------------------------
# Copyright (c) 2012 - 2021, Anaconda, Inc., and Bokeh Contributors.
# All rights reserved.
#
# The full license is in the file LICENSE.txt, distributed with this software.
# -----------------------------------------------------------------------------
""" Display code blocks in collapsible sections when outputting to HTML.

This directive takes a heading to use for the collapsible code block:

.. code-block:: rest

    .. collapsible-code-block:: python
        :heading: Some Code

                print("Hello, Bokeh!")

This directive is identical to the standard ``code-block`` directive
that Sphinx supplies, with the addition of one new option:

heading (string):
    A heading to put for the collapsible block. Clicking the heading
    expands or collapses the block.



Examples
--------

The inline example code above produces the following output:

.. collapsible-code-block:: python
    :heading: Some Code

        print("Hello, Bokeh!")

"""

# -----------------------------------------------------------------------------
# Boilerplate
# -----------------------------------------------------------------------------
import logging  # isort:skip

log = logging.getLogger(__name__)

# -----------------------------------------------------------------------------
# Imports
# -----------------------------------------------------------------------------

# Standard library imports
from os.path import basename

# External imports
from docutils import nodes
from docutils.parsers.rst.directives import unchanged
from sphinx.directives.code import CodeBlock

# Bokeh imports
from .templates import CCB_EPILOGUE, CCB_PROLOGUE

# -----------------------------------------------------------------------------
# Globals and constants
# -----------------------------------------------------------------------------

__all__ = (
    "collapsible_code_block",
    "CollapsibleCodeBlock",
    "html_depart_collapsible_code_block",
    "html_visit_collapsible_code_block",
    "setup",
)

# -----------------------------------------------------------------------------
# General API
# -----------------------------------------------------------------------------

# -----------------------------------------------------------------------------
# Dev API
# -----------------------------------------------------------------------------


class collapsible_code_block(nodes.General, nodes.Element):
    pass


class CollapsibleCodeBlock(CodeBlock):

    option_spec = CodeBlock.option_spec
    option_spec.update(heading=unchanged)

    def run(self):
        env = self.state.document.settings.env

        rst_source = self.state_machine.node.document["source"]
        rst_filename = basename(rst_source)

        serial_no = env.new_serialno("ccb")
        target_id = f"{rst_filename}.ccb-{serial_no}"
        target_id = target_id.replace(".", "-")
        target_node = nodes.target("", "", ids=[target_id])

        node = collapsible_code_block()
        node["target_id"] = target_id
        node["heading"] = self.options.get("heading", "Code")

        cb = CodeBlock.run(self)
        node.setup_child(cb[0])
        node.children.append(cb[0])

        return [target_node, node]


def html_visit_collapsible_code_block(self, node):
    self.body.append(CCB_PROLOGUE.render(id=node["target_id"], heading=node["heading"]))


def html_depart_collapsible_code_block(self, node):
    self.body.append(CCB_EPILOGUE.render())


def setup(app):
    """ Required Sphinx extension setup function. """
    app.add_node(collapsible_code_block, html=(html_visit_collapsible_code_block, html_depart_collapsible_code_block))
    app.add_directive("collapsible-code-block", CollapsibleCodeBlock)


# -----------------------------------------------------------------------------
# Private API
# -----------------------------------------------------------------------------

# -----------------------------------------------------------------------------
# Code
# -----------------------------------------------------------------------------
