import warnings
import json
import random
from .base import Renderer
from ..exporter import Exporter


class VegaRenderer(Renderer):
    def open_figure(self, fig, props):
        self.props = props
        self.figwidth = int(props["figwidth"] * props["dpi"])
        self.figheight = int(props["figheight"] * props["dpi"])
        self.data = []
        self.scales = []
        self.axes = []
        self.marks = []

    def open_axes(self, ax, props):
        if len(self.axes) > 0:
            warnings.warn("multiple axes not yet supported")
        self.axes = [
            dict(type="x", scale="x", ticks=10),
            dict(type="y", scale="y", ticks=10),
        ]
        self.scales = [
            dict(
                name="x",
                domain=props["xlim"],
                type="linear",
                range="width",
            ),
            dict(
                name="y",
                domain=props["ylim"],
                type="linear",
                range="height",
            ),
        ]

    def draw_line(self, data, coordinates, style, label, mplobj=None):
        if coordinates != "data":
            warnings.warn("Only data coordinates supported. Skipping this")
        dataname = "table{0:03d}".format(len(self.data) + 1)

        # TODO: respect the other style settings
        self.data.append(
            {"name": dataname, "values": [dict(x=d[0], y=d[1]) for d in data]}
        )
        self.marks.append(
            {
                "type": "line",
                "from": {"data": dataname},
                "properties": {
                    "enter": {
                        "interpolate": {"value": "monotone"},
                        "x": {"scale": "x", "field": "data.x"},
                        "y": {"scale": "y", "field": "data.y"},
                        "stroke": {"value": style["color"]},
                        "strokeOpacity": {"value": style["alpha"]},
                        "strokeWidth": {"value": style["linewidth"]},
                    }
                },
            }
        )

    def draw_markers(self, data, coordinates, style, label, mplobj=None):
        if coordinates != "data":
            warnings.warn("Only data coordinates supported. Skipping this")
        dataname = "table{0:03d}".format(len(self.data) + 1)

        # TODO: respect the other style settings
        self.data.append(
            {"name": dataname, "values": [dict(x=d[0], y=d[1]) for d in data]}
        )
        self.marks.append(
            {
                "type": "symbol",
                "from": {"data": dataname},
                "properties": {
                    "enter": {
                        "interpolate": {"value": "monotone"},
                        "x": {"scale": "x", "field": "data.x"},
                        "y": {"scale": "y", "field": "data.y"},
                        "fill": {"value": style["facecolor"]},
                        "fillOpacity": {"value": style["alpha"]},
                        "stroke": {"value": style["edgecolor"]},
                        "strokeOpacity": {"value": style["alpha"]},
                        "strokeWidth": {"value": style["edgewidth"]},
                    }
                },
            }
        )

    def draw_text(
        self, text, position, coordinates, style, text_type=None, mplobj=None
    ):
        if text_type == "xlabel":
            self.axes[0]["title"] = text
        elif text_type == "ylabel":
            self.axes[1]["title"] = text


class VegaHTML(object):
    def __init__(self, renderer):
        self.specification = dict(
            width=renderer.figwidth,
            height=renderer.figheight,
            data=renderer.data,
            scales=renderer.scales,
            axes=renderer.axes,
            marks=renderer.marks,
        )

    def html(self):
        """Build the HTML representation for IPython."""
        id = random.randint(0, 2**16)
        html = '
' % id html += "\n" return html def _repr_html_(self): return self.html() def fig_to_vega(fig, notebook=False): """Convert a matplotlib figure to vega dictionary if notebook=True, then return an object which will display in a notebook otherwise, return an HTML string. """ renderer = VegaRenderer() Exporter(renderer).run(fig) vega_html = VegaHTML(renderer) if notebook: return vega_html else: return vega_html.html() VEGA_TEMPLATE = """ ( function() { var _do_plot = function() { if ( (typeof vg == 'undefined') && (typeof IPython != 'undefined')) { $([IPython.events]).on("vega_loaded.vincent", _do_plot); return; } vg.parse.spec(%s, function(chart) { chart({el: "#vis%d"}).update(); }); }; _do_plot(); })(); """