from flask_json import as_json
from bokeh.embed import json_item
from marshmallow import Schema, fields, validate
from webargs.flaskparser import use_args

from flexmeasures.auth.decorators import account_roles_accepted
from flexmeasures.api.v2_0 import flexmeasures_api as flexmeasures_api_v2_0
from flexmeasures.api.v2_0.routes import v2_0_service_listing
from flexmeasures.data.schemas.times import DurationField
from flexmeasures.data.queries.analytics import get_power_data
from flexmeasures.ui.views.analytics import make_power_figure


"""
An endpoint to get a power chart.

This chart view is considered legacy now. See flexmeasures/data/models/charts for our new approach
to support charts per API, using Altair and the Sensor ID.
It also uses the old data model.
"""


v2_0_service_listing["services"].append(
    {
        "name": "GET /charts/power",
        "access": ["admin", "Prosumer"],
        "description": "Get a Bokeh chart for power data to embed in web pages.",
    },
)


class ChartRequestSchema(Schema):
    """
    This schema describes the request for a chart.
    """

    resource = fields.Str(required=True)
    start_time = fields.DateTime(required=True)
    end_time = fields.DateTime(required=True)
    resolution = DurationField(required=True)
    show_consumption_as_positive = fields.Bool(missing=True)
    show_individual_traces_for = fields.Str(
        missing="none", validate=validate.OneOf(["none", "schedules", "power"])
    )
    forecast_horizon = DurationField(missing="PT6H")


@flexmeasures_api_v2_0.route("/charts/power", methods=["GET"])
@account_roles_accepted("Prosumer")
@use_args(ChartRequestSchema(), location="querystring")
@as_json
def get_power_chart(chart_request):
    """API endpoint to get a chart for power data which can be embedded in web pages.

    .. :quickref: Chart; Get a power chart

    This endpoint returns a Bokeh chart with power data which can be embedded in a website.
    It includes forecasts and even schedules, if available.

    **Example request**

    An example of a chart request:

    .. sourcecode:: json

        {
            "resource": ""my-battery,
            "start_time": "2020-02-20:10:00:00UTC",
            "end_time": "2020-02-20:11:00:00UTC",
            "resolution": "PT15M",
            "consumption_as_positive": true
            "resolution": "PT6H",
            "show_individual_traces_for": "none"  // can be power or schedules
        }

    On your webpage, you need to include the Bokeh libraries, e.g.:

        <script src="https://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.js"></script>

    (The version needs to match the version used by the FlexMeasures server, see requirements/app.txt)

    Then you can call this endpoint and include the result like this:

    .. sourcecode:: javascript

        <script>
            fetch('http://localhost:5000/api/v2_0/charts/power?' + urlData.toString(),
            {
                method: "GET",
                mode: "cors",
                headers:
                    {
                        "Content-Type": "application/json",
                        "Authorization": "<users auth token>"
                    },
            })
            .then(function(response) { return response.json(); })
            .then(function(item) { Bokeh.embed.embed_item(item, "<ID of the div >"); });
        </script>

    where `urlData` is a `URLSearchData` object and contains the chart request parameters (see above).

    :reqheader Authorization: The authentication token
    :reqheader Content-Type: application/json
    :resheader Content-Type: application/json
    :status 200: PROCESSED
    :status 400: INVALID_REQUEST
    :status 401: UNAUTHORIZED
    :status 403: INVALID_SENDER
    :status 422: UNPROCESSABLE_ENTITY
    """
    data = get_power_data(
        resource=chart_request["resource"],
        show_consumption_as_positive=chart_request["show_consumption_as_positive"],
        showing_individual_traces_for=chart_request["show_individual_traces_for"],
        metrics={},  # will be stored here, we don't need them for now
        query_window=(chart_request["start_time"], chart_request["end_time"]),
        resolution=chart_request["resolution"],
        forecast_horizon=chart_request["forecast_horizon"],
    )
    figure = make_power_figure(
        resource_display_name=chart_request["resource"],
        data=data[0],
        forecast_data=data[1],
        schedule_data=data[2],
        show_consumption_as_positive=chart_request["show_consumption_as_positive"],
        shared_x_range=None,
        sizing_mode="scale_both",
    )
    return json_item(figure)
