# I HATE MATPLOTLIB AND PYTHON
# I HATE MATPLOTLIB AND PYTHON
# I HATE MATPLOTLIB AND PYTHON
# I HATE MATPLOTLIB AND PYTHON
# I HATE MATPLOTLIB AND PYTHON
# I HATE MATPLOTLIB AND PYTHON
# I HATE MATPLOTLIB AND PYTHON
# I HATE MATPLOTLIB AND PYTHON
# I HATE MATPLOTLIB AND PYTHON
# I HATE MATPLOTLIB AND PYTHON
# I HATE MATPLOTLIB AND PYTHON
# I HATE MATPLOTLIB AND PYTHON
# I HATE MATPLOTLIB AND PYTHON
# I HATE MATPLOTLIB AND PYTHON
# I HATE MATPLOTLIB AND PYTHON
# I HATE MATPLOTLIB AND PYTHON
# I HATE MATPLOTLIB AND PYTHON
# I HATE MATPLOTLIB AND PYTHON
# I HATE MATPLOTLIB AND PYTHON
# I HATE MATPLOTLIB AND PYTHON
# I HATE MATPLOTLIB AND PYTHON
# I HATE MATPLOTLIB AND PYTHON
# I HATE MATPLOTLIB AND PYTHON
# I HATE MATPLOTLIB AND PYTHON
# I HATE MATPLOTLIB AND PYTHON
# I HATE MATPLOTLIB AND PYTHON
# I HATE MATPLOTLIB AND PYTHON
# I HATE MATPLOTLIB AND PYTHON
# I HATE MATPLOTLIB AND PYTHON
# I HATE MATPLOTLIB AND PYTHON
# I HATE MATPLOTLIB AND PYTHON

"""Routes plots."""
import matplotlib
import seaborn
import json, textwrap, io, surveyparser, readingparser, pandas, math, textwrap
from bottle import Bottle, route, view, response, request, abort

BAD = "#c12f4d"
OK = "#F29E22"
GOOD = "#5FA05A"
PRIMARY = "#AA228C"
SECONDARY = "#F07024"
MAX_SATISF_CHARS = 15

# Change default matplotlib style
# HACK What the fuck
seaborn.set(font = "Helvetica Neue", rc = {
    "axes.axisbelow": False,
    "axes.edgecolor": "#dedddc",
    "axes.facecolor": "None",
    "axes.grid": False,
    "axes.labelcolor": "#161616",
    "axes.spines.right": False,
    "axes.spines.top": False,
    "figure.facecolor": "white",
    "lines.solid_capstyle": "round",
    "patch.edgecolor": "w",
    "patch.force_edgecolor": True,
    "text.color": "#161616",
    "xtick.bottom": False,
    "xtick.color": "#161616",
    "xtick.direction": "out",
    "xtick.top": False,
    "ytick.color": "#161616",
    "ytick.direction": "out",
    "ytick.left": False,
    "ytick.right": False
})
seaborn.set_context("notebook", rc = {
    "font.size": 16,
    "axes.titlesize": 20,
    "axes.labelsize": 18,
    "figure.dpi": 100,
    "savefig.dpi":300
})

plot = Bottle()

# HACK I HATE PYTHON I HATE PYTHON I HATE PYTHON
def autopct(pct): # only show the label when it's > 10%
    return ('%.0f%%' % pct) if pct > 50 else ''

@plot.route("/surveys/<name>/plot.png")
def plot_reading(name):
    survey, properties = surveyparser.get_survey(name)
    selected_answers = json.loads(request.query.get("selected-answers"))
    type = request.query.get("type")
    reading = request.query.get("reading")
    question = request.query.get("question")
    plot = request.query.get("plot")
    good_regex = request.query.get("good-regex")
    bad_regex = request.query.get("bad-regex")

    readings = surveyparser.get_readings(name)
    reading = readings[int(reading)]

    # Filter survey
    survey = surveyparser.filter_survey(survey, properties, surveyparser.get_metadata(name), selected_answers)

    # TODO Support choice reading
    dataframe = survey[reading[question]]
    colors = [ PRIMARY, SECONDARY ]

    # HACK This is a warcrime, I'm so sorry if you have to read this
    if type == "satisfaction":
        satisfaction = readingparser.classify(survey[reading[question]].to_frame(), reading[good_regex], reading[bad_regex], True)
        dataframe = pandas.DataFrame.from_dict({
            "Insatisfecho/a": [satisfaction[reading[question]]["bad"]],
            "Ni ni": [satisfaction[reading[question]]["neither"]],
            "Satisfecho/a": [satisfaction[reading[question]]["good"]]
        }).T
        colors = [ GOOD , OK, BAD ]

    # Plot
    fig, ax = matplotlib.pyplot.subplots()

    if reading[plot] == "Dona partida":
        if type == "satisfaction":
            dataframe = dataframe[dataframe > 0] # Remove zeros

        dataframe = (dataframe.value_counts(normalize=True) * 100)
        ax = dataframe.plot.pie(
            ylabel = "",
            colors = colors,
            autopct = "%.1f%%",
            fontsize = 16,
            pctdistance = 0.775,
            textprops = { "color": "white", "weight": "bold" },
            labels = None
        )

        # Make into donut
        circle = matplotlib.pyplot.Circle((0, 0), 0.6, color = "white")
        fig.gca().add_artist(circle)

        fig.tight_layout()

    if reading[plot] == "Dona total":
        colors = [ GOOD, "#00000000" ]

        ax = dataframe.squeeze().plot.pie(
            ylabel = "",
            colors = colors,
            autopct = autopct,
            fontsize = 32,
            pctdistance = 0,
            textprops = { "color": "#999999" },
            startangle = 90,
            labels = None,
        )

        # Make into donut
        circle = matplotlib.pyplot.Circle((0, 0), 0.6, color = "white")
        fig.gca().add_artist(circle)

        fig.tight_layout()

    elif reading[plot] == "Barras verticales":
        dataframe = (dataframe.value_counts(normalize=True) * 100)
        ax = dataframe.plot.bar(color = colors)

        # FIXME Only works on newer matplotlib versions
        boxes = ax.bar_label(ax.containers[0], fmt = "%.0f%%", padding = 2)
        for i in range(len(boxes)):
            boxes[i].set_fontsize(20)
            boxes[i].set_color(colors[i % len(colors)])

        title = "\n".join(textwrap.wrap(reading[question], 30)) # TODO Make 30 const
        ax.set_title(title, pad=40)

        # HACK 💀️
        if type == "satisfaction":
            ax.get_xaxis().set_visible(False)
        ax.get_yaxis().set_visible(False)
        ax.spines["top"].set_visible(False)
        ax.spines["right"].set_visible(False)
        ax.spines["bottom"].set_visible(True)
        ax.spines["left"].set_visible(False)

        # HACK I HATE MATPLOTLIB
        # HACK I HATE MATPLOTLIB
        # HACK I HATE MATPLOTLIB
        # HACK I HATE MATPLOTLIB
        new_texts = []
        for tick in ax.get_xticklabels():
            tick.set_fontsize(16)
            tick.set_rotation(0)
            text = "\n".join(textwrap.wrap(tick.get_text(), 10)) # TODO Make 10 const
            new_texts.append(text)

        ax.set_xticklabels(new_texts) # HACK I HATE MATPLOTLIB

    # Output to object
    png_output = io.BytesIO()
    fig.savefig(png_output, format = "svg", bbox_inches = "tight")
    response.content_type = "image/svg+xml"
    matplotlib.pyplot.close()
    matplotlib.pyplot.figure().clear()

    return png_output.getvalue()
