#
# Copyright (c) 2019. JetBrains s.r.o.
# Use of this source code is governed by the MIT license that can be found in the LICENSE file.
#
from typing import Dict, Any

from ._frontend_ctx import FrontendContext
from ._html_contexts import _create_html_frontend_context, _create_wb_html_frontend_context
from ._json_contexts import _create_json_frontend_context, _is_Intellij_Python_Lets_Plot_Plugin
from ._mime_types import TEXT_HTML, LETS_PLOT_JSON
from ._static_svg_ctx import StaticSvgImageContext
from ._webbr_html_page_ctx import WebBrHtmlPageContext
from .._version import __version__
from ..plot.core import PlotSpec
from ..plot.plot import GGBunch
from ..plot.subplots import SupPlotsSpec

__all__ = []

_frontend_contexts: Dict[str, FrontendContext] = {}

_default_mimetype = TEXT_HTML
if _is_Intellij_Python_Lets_Plot_Plugin():
    _default_mimetype = LETS_PLOT_JSON
    _frontend_contexts[LETS_PLOT_JSON] = _create_json_frontend_context()


def _setup_html_context(*,
                        isolated_frame: bool = None,
                        offline: bool,
                        no_js: bool,
                        show_status: bool,
                        dev_options: Dict = None) -> None:
    """
    Configures Lets-Plot HTML output.
    See the docstring in `setup_html()` for details on parameters.
    """
    global _default_mimetype
    if _default_mimetype == LETS_PLOT_JSON:
        # Plots will be rendered by Lets-Plot IntelliJ plugin.
        # But still create HTML context in case it's necessary.
        if show_status:
            print(
                'Lets-Plot v{}: output mimetype {} configured by default. No need for HTML output.'.format(__version__,
                                                                                                           LETS_PLOT_JSON))

    if no_js:
        ctx = StaticSvgImageContext()
    else:
        ctx = _create_html_frontend_context(isolated_frame, offline=offline, dev_options=dev_options)

    ctx.configure(verbose=show_status)
    _frontend_contexts[TEXT_HTML] = ctx


def _setup_wb_html_context(*,
                           exec: str,
                           new: bool) -> None:
    """
    Configures Lets-Plot HTML output for showing in a browser.

    Parameters
    ----------
    exec : str, optional
        Command to execute to open the plot in a web browser.
        If not specified, the default browser will be used.
    new : bool, default=False
        If True, the URL is opened in a new window of the web browser.
        If False, the URL is opened in the already opened web browser window.
    """
    ctx = _create_wb_html_frontend_context(exec, new)
    _frontend_contexts[TEXT_HTML] = ctx


def _display_plot(spec: Any):
    """
    Draw plot or `bunch` of plots in the current frontend context
    :param spec: PlotSpec or GGBunch object
    """
    if not (isinstance(spec, PlotSpec) or isinstance(spec, SupPlotsSpec) or isinstance(spec, GGBunch)):
        raise ValueError("PlotSpec or SupPlotsSpec expected but was: {}".format(type(spec)))

    if _default_mimetype == TEXT_HTML:
        ctx = _frontend_contexts.get(TEXT_HTML)

        if ctx is not None and isinstance(ctx, WebBrHtmlPageContext):
            ctx.show(spec.as_dict())
            return

        # If ctx is None, _as_html() will try to initialize the context lazily
        plot_html = _as_html(spec.as_dict())
        try:
            from IPython.display import display_html
            display_html(plot_html, raw=True)
            return
        except ImportError:
            pass

        print(spec.as_dict())
        return

    if _default_mimetype == LETS_PLOT_JSON:
        _frontend_contexts[LETS_PLOT_JSON].show(spec.as_dict())
        return

    # fallback to plain text.
    print(spec.as_dict())


def _as_html(plot_spec: Dict) -> str:
    """
    Creates plot HTML using 'html' frontend context.

    :param plot_spec: dict
    """
    ctx = _frontend_contexts.get(TEXT_HTML)

    if ctx is None:
        # Set up HTML context lazily
        _setup_html_context(isolated_frame=None,
                            offline=False,
                            no_js=False,
                            show_status=False)

        ctx = _frontend_contexts[TEXT_HTML]

        # Check if this context allows lazy set-up.
        requires_configure = getattr(ctx, 'requires_configure', False)
        if requires_configure:
            # Clear the context and return an error message
            _frontend_contexts[TEXT_HTML] = None
            return """\
            <div style="color:darkred;">
                Lets-plot `html` is not configured.<br>
                Try to use `LetsPlot.setup_html()` before first occurrence of plot.
            </div>
            """

    # Generate "display" HTML
    return ctx.as_str(plot_spec)
