"""
pygal Tag
---------
This implements a Liquid-style pygal tag for Pelican. JSON is used for the data,
and you can pass a bunch of pygal's 'config' items through as-is

[1] http://www.pygal.org/

Syntax
------
{% pygal
    {
        <graph data>
    }
%}

Examples
--------
{%
    pygal {
        "type": "bar",
        "title": "Test Chart",
        "x-labels" : {"from": 2002, "to": 2013},
        "data" : [
        {"title": "Firefox",
         "values": [null, null, 0, 16.6,   25,   31, 36.4, 45.5, 46.3, 42.8, 37.1]},
         {"title": "Chrome",
         "values": [null, null, null, null, null, null,    0,  3.9, 10.8, 23.8, 35.3]},
         {"title": "IE",
         "values": [85.8, 84.6, 84.7, 74.5,   66, 58.6, 54.7, 44.8, 36.2, 26.6, 20.1]},
         {"title": "Others",
         "values": [14.2, 15.4, 15.3,  8.9,    9, 10.4,  8.9,  5.8,  6.7,  6.8,  7.5]}
        ]
    }
%}

{%
    pygal {
        "type": "pie",
        "half_pie": true,
        "title": "Browser usage in February 2012 (in %)",
        "data" : [
        {"title": "IE",
         "values": 19.5},
         {"title": "Firefox",
         "values": 36.6},
         {"title": "Chrome",
         "values": 36.3},
         {"title": "Safari",
         "values": 4.5},
         {"title": "Opera",
         "values": 2.3}
        ]
    }
%}

{%
    pygal {
        "type": "pie",
            "config": {
            "show_legend": false,
            "print_values": true,
            "show_y_labels": true
        },
        "title": "Browser usage in February 2012 (in %)",
        "data" : [
        {"title": "IE",
         "values": 19.5},
         {"title": "Firefox",
         "values": 36.6},
         {"title": "Chrome",
         "values": 36.3},
         {"title": "Safari",
         "values": 4.5},
         {"title": "Opera",
         "values": 2.3}
        ]
    }
%}



...


Output
------
<<div class="pygal" style="text-align: center;"><embed type="image/svg+xml" src=SVG_MARKUP_EMBEDDED style="max-width:1000px"/></div>

"""

from json import loads
import re

from .mdx_liquid_tags import LiquidTags

SYNTAX = "{% pygal (data) %}"
DOT_BLOCK_RE = re.compile(r"^\s*\{\s*(?P<code>.*\})\s*\}$", re.MULTILINE | re.DOTALL)


def run_pygal(data, options=[], format="svg"):
    """Runs pygal programs and returns image data"""
    import pygal

    chart_type = data.get("type", "").lower()
    # Config options are pretty much proxied straight through from the JSON dict into the object
    config = pygal.Config()
    config_dict = data.get("config", {})
    for key in config_dict.keys():
        setattr(config, key, config_dict[key])

    if chart_type == "bar":
        chart = (
            pygal.HorizontalBar(config)
            if data.get("horizontal", False)
            else pygal.Bar(config)
        )
    elif chart_type == "line":
        chart = pygal.Line(config)
    elif chart_type == "pie":
        ir = data.get("inner_radius", 0.0)
        hp = data.get("half_pie", False)
        chart = pygal.Pie(config, inner_radius=ir, half_pie=hp)
    else:
        print("undefined or unknown chart type")

    if chart is not None:
        chart.title = data.get("title", None)
        # Do labels (if present)
        label_data = data.get("x-labels", None)
        if isinstance(label_data, list):
            # use list
            chart.x_labels = label_data
        elif isinstance(label_data, dict):
            # use a range
            range_from = label_data.get("from", 0)
            range_to = label_data.get("to", 0)
            chart.x_labels = map(str, range(range_from, range_to))
        # insert data
        for data_set in data.get("data", []):
            title = data_set.get("title", None)
            values = data_set.get("values", None)
            chart.add(title, values)
        # now render
        result = chart.render_data_uri()
    else:
        result = None
    return result


@LiquidTags.register("pygal")
def pygal_parser(preprocessor, tag, markup):
    """Simple pygal parser"""
    # Find JSON payload
    data = loads(markup)
    if tag == "pygal" and data is not None:
        # Run generation of chart
        output = run_pygal(data)
        # Return embedded SVG image
        return (
            '<div class="pygal" style="text-align: center;"><embed type="image/svg+xml" src=%s style="max-width:1000px"/></div>'
            % output
        )

    else:
        raise ValueError(f"Error processing input. \nExpected syntax: {SYNTAX}")


# ----------------------------------------------------------------------
# This import allows pygal tag to be a Pelican plugin
from .liquid_tags import register  # noqa
