# -----------------------------------------------------------------------------
# Copyright (c) Anaconda, Inc., and Bokeh Contributors.
# All rights reserved.
#
# The full license is in the file LICENSE.txt, distributed with this software.
# -----------------------------------------------------------------------------
""" Generate visual representations of palettes in Bokeh palette groups.

The ``bokeh.palettes`` modules expose attributes such as ``mpl``, ``brewer``,
and ``d3`` that provide groups of palettes. The ``bokeh-palette-group``
directive accepts the name of one of these groups, and generates a visual
matrix of colors for every palette in the group.

As an example, the following usage of the directive:

.. code-block:: rest

    .. bokeh-palette-group:: mpl

Generates the output:

-----

.. bokeh-palette-group:: mpl

"""

# -----------------------------------------------------------------------------
# Boilerplate
# -----------------------------------------------------------------------------
from __future__ import annotations

import logging  # isort:skip

log = logging.getLogger(__name__)

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

# External imports
from docutils import nodes
from docutils.parsers.rst import Directive
from sphinx.errors import SphinxError

# Bokeh imports
import bokeh.palettes as bp

# Bokeh imports
from . import PARALLEL_SAFE
from .templates import PALETTE_GROUP_DETAIL

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

__all__ = (
    "bokeh_palette_group",
    "BokehPaletteGroupDirective",
    "setup",
)

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

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


class bokeh_palette_group(nodes.General, nodes.Element):

    @staticmethod
    def visit_html(visitor, node):
        visitor.body.append('<div class="container-fluid"><div class="row">')
        group = getattr(bp, node["group"], None)
        if not isinstance(group, dict):
            group_name = node["group"]
            raise SphinxError(f"invalid palette group name {group_name}")
        names = sorted(group)
        for name in names:
            palettes = group[name]
            # arbitrary cutoff here, idea is to not show large (e.g. 256 length) palettes
            numbers = [x for x in sorted(palettes) if x < 30]
            html = PALETTE_GROUP_DETAIL.render(name=name, numbers=numbers, palettes=palettes)
            visitor.body.append(html)
        visitor.body.append("</div></div>")
        raise nodes.SkipNode

    html = visit_html.__func__, None


class BokehPaletteGroupDirective(Directive):

    has_content = False
    required_arguments = 1

    def run(self):
        node = bokeh_palette_group()
        node["group"] = self.arguments[0]
        return [node]


def setup(app):
    """ Required Sphinx extension setup function. """
    app.add_node(bokeh_palette_group, html=bokeh_palette_group.html)
    app.add_directive("bokeh-palette-group", BokehPaletteGroupDirective)

    return PARALLEL_SAFE

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

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