import pandas as pd

from bokeh.models import HoverTool
from bokeh.models.formatters import DatetimeTickFormatter
from bokeh.palettes import Plasma256
from bokeh.plotting import figure, ColumnDataSource

from app import db
from app.decorators import data_quality

# creates your plot
date_formatter = DatetimeTickFormatter(microseconds=['%f'],
                                       milliseconds=['%S.%2Ns'],
                                       seconds=[':%Ss'],
                                       minsec=[':%Mm:%Ss'],
                                       minutes=['%H:%M:%S'],
                                       hourmin=['%H:%M:'],
                                       hours=["%H:%M"],
                                       days=["%d %b"],
                                       months=["%d %b %Y"],
                                       years=["%b %Y"])


def get_position_source(start_date, end_date, obsmode):
    logic = "   and HrsMode_Id = {obsmode} " \
            "   and FileName like 'RORDER%%' " \
        .format(obsmode=obsmode)
    sql = "select Date, y_upper, HrsOrder, CONVERT(Date,char) AS Time " \
          "     from DQ_HrsOrder join NightInfo using (NightInfo_Id) " \
          "     where Date > '{start_date}' and Date <'{end_date}' {logic}" \
        .format(start_date=start_date, end_date=end_date, logic=logic)
    df = pd.read_sql(sql, db.engine)
    colors = []
    if len(df) > 0:
        ord_min = df['HrsOrder'].min()
        ord_max = df['HrsOrder'].max()
        colors = [Plasma256[int((y - ord_min) * (len(Plasma256) - 1) / float(ord_max - ord_min))] for y in
                  df["HrsOrder"]]

    df['colors'] = colors

    source = ColumnDataSource(df)
    return source


@data_quality(name='hrs_order', caption='HRS Order')
def hrs_order_plot(start_date, end_date):
    """Return a <div> element with the Order plot.

    The plot shows the HRS order for obsmode High, low and medium over time

    Params:
    -------
    start_date: date
        Earliest date to include in the plot.
    end_date: date
        Earliest date not to include in the plot.

    Return:
    -------
    str:
        A <div> element with the Order plot.
    """

    def get_source(obsmode):
        logic = "   and HrsMode_Id = {obsmode} " \
                "   and FileName like 'RORDER%%' " \
                "   group by Date " \
            .format(obsmode=obsmode)
        sql = "select Date, (Max(HrsOrder) - Min(HrsOrder)) as ord, CONVERT(Date, char) AS Time " \
              "     from DQ_HrsOrder join NightInfo using (NightInfo_Id) " \
              "     where Date > '{start_date}' and Date <'{end_date}' {logic}" \
            .format(start_date=start_date, end_date=end_date, logic=logic)
        df = pd.read_sql(sql, db.engine)

        source = ColumnDataSource(df)
        return source

    low_source = get_source(1)  # HrsMode_Id = 1 low
    med_source = get_source(2)  # HrsMode_Id = 2 med
    high_source = get_source(3)  # HrsMode_Id = 3 high

    tool_list = "pan,reset,save,wheel_zoom, box_zoom"
    _hover = HoverTool(
        tooltips="""
                <div>
                    <div>
                        <span style="font-size: 15px; font-weight: bold;">Date: </span>
                        <span style="font-size: 15px;"> @Time</span>
                    </div>
                    <div>
                        <span style="font-size: 15px; font-weight: bold;">HrsOrder(Max - Min): </span>
                        <span style="font-size: 15px;"> @ord</span>
                    </div>
                </div>
                """
    )

    p = figure(title="HRS Order",
               x_axis_label='Date',
               y_axis_label='Max(HrsOrder) - Min(HrsOrder)',
               x_axis_type='datetime',
               tools=[tool_list, _hover])
    p.scatter(source=low_source, x='Date', y='ord', color='red', fill_alpha=0.2, legend='Low', size=10)
    p.scatter(source=med_source, x='Date', y='ord', color='orange', fill_alpha=0.2, legend='Medium', size=10)
    p.scatter(source=high_source, x='Date', y='ord', color='green', fill_alpha=0.2, legend='High', size=10)

    p.legend.location = "top_right"
    p.legend.click_policy = "hide"
    p.legend.background_fill_alpha = 0.3
    p.legend.inactive_fill_alpha = 0.8

    p.xaxis[0].formatter = date_formatter

    return p


@data_quality(name='hrs_order_position_high', caption=' ')
def hrs_order_position_plot(start_date, end_date):
    """
        Return a <div> element with the Order Position plot.

        The plot shows the HRS order for obsmode High resolution over time

        Params:
        -------
        start_date: date
            Earliest date to include in the plot.
        end_date: date
            Earliest date not to include in the plot.

        Return:
        -------
        str:
            A <div> element with the Order Position plot.
    """

    high_source = get_position_source(start_date, end_date, 3)  # HrsMode_Id = 3 high

    tool_list = "pan,reset,save,wheel_zoom, box_zoom"
    _hover = HoverTool(
        tooltips="""
                <div>
                    <div>
                        <span style="font-size: 15px; font-weight: bold;">Date: </span>
                        <span style="font-size: 15px;"> @Time</span>
                    </div>
                    <div>
                        <span style="font-size: 15px; font-weight: bold;">Y Upper: </span>
                        <span style="font-size: 15px;"> @y_upper</span>
                    </div>
                    <div>
                        <span style="font-size: 15px; font-weight: bold;">HRS Order: </span>
                        <span style="font-size: 15px;"> @HrsOrder</span>
                    </div>
                </div>
                """
    )

    p = figure(title="HRS Order Position High Resolution",
               x_axis_label='Date',
               y_axis_label='y_upper',
               x_axis_type='datetime',
               tools=[tool_list, _hover])
    p.scatter(source=high_source, x='Date', y='y_upper', color='colors', fill_alpha=0.2, size=10)

    p.xaxis[0].formatter = date_formatter

    return p


@data_quality(name='hrs_order_position_medium', caption=' ')
def hrs_order_position_plot(start_date, end_date):
    """
        Return a <div> element with the Order Position plot.

        The plot shows the HRS order for obsmode High resolution over time

        Params:
        -------
        start_date: date
            Earliest date to include in the plot.
        end_date: date
            Earliest date not to include in the plot.

        Return:
        -------
        str:
            A <div> element with the Order Position plot.
    """

    high_source = get_position_source(start_date, end_date, 2)  # HrsMode_Id = 3 high

    tool_list = "pan,reset,save,wheel_zoom, box_zoom"
    _hover = HoverTool(
        tooltips="""
                <div>
                    <div>
                        <span style="font-size: 15px; font-weight: bold;">Date: </span>
                        <span style="font-size: 15px;"> @Time</span>
                    </div>
                    <div>
                        <span style="font-size: 15px; font-weight: bold;">Y Upper: </span>
                        <span style="font-size: 15px;"> @y_upper</span>
                    </div>
                    <div>
                        <span style="font-size: 15px; font-weight: bold;">HRS Order: </span>
                        <span style="font-size: 15px;"> @HrsOrder</span>
                    </div>
                </div>
                """
    )

    p = figure(title="HRS Order Position Medium Resolution",
               x_axis_label='Date',
               y_axis_label='y_upper',
               x_axis_type='datetime',
               tools=[tool_list, _hover])
    p.scatter(source=high_source, x='Date', y='y_upper', color='colors', fill_alpha=0.2, size=10)

    p.xaxis[0].formatter = date_formatter

    return p


@data_quality(name='hrs_order_position_low', caption=' ')
def hrs_order_position_plot(start_date, end_date):
    """
        Return a <div> element with the Order Position plot.

        The plot shows the HRS order for obsmode High resolution over time

        Params:
        -------
        start_date: date
            Earliest date to include in the plot.
        end_date: date
            Earliest date not to include in the plot.

        Return:
        -------
        str:
            A <div> element with the Order Position plot.
    """

    high_source = get_position_source(start_date, end_date, 3)  # HrsMode_Id = 3 high

    tool_list = "pan,reset,save,wheel_zoom, box_zoom"
    _hover = HoverTool(
        tooltips="""
                <div>
                    <div>
                        <span style="font-size: 15px; font-weight: bold;">Date: </span>
                        <span style="font-size: 15px;"> @Time</span>
                    </div>
                    <div>
                        <span style="font-size: 15px; font-weight: bold;">Y Upper: </span>
                        <span style="font-size: 15px;"> @y_upper</span>
                    </div>
                    <div>
                        <span style="font-size: 15px; font-weight: bold;">HRS Order: </span>
                        <span style="font-size: 15px;"> @HrsOrder</span>
                    </div>
                </div>
                """
    )

    p = figure(title="HRS Order Position Low Resolution",
               x_axis_label='Date',
               y_axis_label='y_upper',
               x_axis_type='datetime',
               tools=[tool_list, _hover])
    p.scatter(source=high_source, x='Date', y='y_upper', color='colors', fill_alpha=0.2, size=10)

    p.xaxis[0].formatter = date_formatter

    return p
[((12, 17, 21, 55), 'bokeh.models.formatters.DatetimeTickFormatter', 'DatetimeTickFormatter', (), '', False, 'from bokeh.models.formatters import DatetimeTickFormatter\n'), ((46, 1, 46, 52), 'app.decorators.data_quality', 'data_quality', (), '', False, 'from app.decorators import data_quality\n'), ((118, 1, 118, 58), 'app.decorators.data_quality', 'data_quality', (), '', False, 'from app.decorators import data_quality\n'), ((172, 1, 172, 60), 'app.decorators.data_quality', 'data_quality', (), '', False, 'from app.decorators import data_quality\n'), ((226, 1, 226, 57), 'app.decorators.data_quality', 'data_quality', (), '', False, 'from app.decorators import data_quality\n'), ((32, 9, 32, 36), 'pandas.read_sql', 'pd.read_sql', ({(32, 21, 32, 24): 'sql', (32, 26, 32, 35): 'db.engine'}, {}), '(sql, db.engine)', True, 'import pandas as pd\n'), ((42, 13, 42, 33), 'bokeh.plotting.ColumnDataSource', 'ColumnDataSource', ({(42, 30, 42, 32): 'df'}, {}), '(df)', False, 'from bokeh.plotting import figure, ColumnDataSource\n'), ((84, 13, 97, 5), 'bokeh.models.HoverTool', 'HoverTool', (), '', False, 'from bokeh.models import HoverTool\n'), ((99, 8, 103, 41), 'bokeh.plotting.figure', 'figure', (), '', False, 'from bokeh.plotting import figure, ColumnDataSource\n'), ((141, 13, 158, 5), 'bokeh.models.HoverTool', 'HoverTool', (), '', False, 'from bokeh.models import HoverTool\n'), ((160, 8, 164, 41), 'bokeh.plotting.figure', 'figure', (), '', False, 'from bokeh.plotting import figure, ColumnDataSource\n'), ((195, 13, 212, 5), 'bokeh.models.HoverTool', 'HoverTool', (), '', False, 'from bokeh.models import HoverTool\n'), ((214, 8, 218, 41), 'bokeh.plotting.figure', 'figure', (), '', False, 'from bokeh.plotting import figure, ColumnDataSource\n'), ((249, 13, 266, 5), 'bokeh.models.HoverTool', 'HoverTool', (), '', False, 'from bokeh.models import HoverTool\n'), ((268, 8, 272, 41), 'bokeh.plotting.figure', 'figure', (), '', False, 'from bokeh.plotting import figure, ColumnDataSource\n'), ((74, 13, 74, 40), 'pandas.read_sql', 'pd.read_sql', ({(74, 25, 74, 28): 'sql', (74, 30, 74, 39): 'db.engine'}, {}), '(sql, db.engine)', True, 'import pandas as pd\n'), ((76, 17, 76, 37), 'bokeh.plotting.ColumnDataSource', 'ColumnDataSource', ({(76, 34, 76, 36): 'df'}, {}), '(df)', False, 'from bokeh.plotting import figure, ColumnDataSource\n')]