# -*- coding: utf-8 -*-
""" FORECAST TAB """

from datetime import datetime as dt
from datetime import timedelta
import dash_bootstrap_components as dbc
from dash import dcc
from dash import html
import logging

from map_handler import FORECAST_MAX
from map_handler import FREQ
from map_handler import DEBUG
from map_handler import START_DATE, END_DATE, DELAY, DELAY_DATE
from map_handler import WAS
from map_handler import DISCLAIMER_MODELS
from map_handler import PATHS
from tabs.generic import get_forecast_days, layout_view, timeseries


def gen_ts_marks(ts_type, curdate=END_DATE):
    """ Generate time slider marks

    Parameters
    ----------
    ts_type : str
        Time slider type (e.g. was)
    curdate : str, optional
        Current date, by default END_DATE

    Returns
    -------
    dict
        Time slider details
    """

    logging.debug("TS MARKS %s %s", ts_type, curdate)
    if ts_type == 'was':
        forecast_dict = get_forecast_days(curdate)
        forecast_values = sorted(forecast_dict.keys())
        fcst_min = forecast_values[0]
        fcst_max = forecast_values[-1]
        play = False
        freq = 1
    elif ts_type == 'prob':
        forecast_dict = get_forecast_days(curdate)
        if min(forecast_dict.keys()) == 1:
            forecast_dict = dict([
                (idx-1, forecast_dict[idx]) for idx in forecast_dict
                ])

        forecast_values = sorted(forecast_dict.keys())
        fcst_min = forecast_values[0]
        fcst_max = forecast_values[-1]
        play = False
        freq = 1
    else:
        fcst_min = 0
        fcst_max = FORECAST_MAX
        forecast_values = range(fcst_min, fcst_max+FREQ, FREQ)
        forecast_dict = dict([
                (fcst_val, f'{fcst_val}') for fcst_val in forecast_values
                ])
                
        play = True
        freq = FREQ

    return {
        'min': fcst_min,
        'max': fcst_max,
        'step': freq,
        'marks': forecast_dict,
        'play': play
    }


def gen_time_slider(ts_type='prob', end_date=END_DATE):
    """ Generate time slider

    Parameters
    ----------
    ts_type : str, optional
        Time slider type, by default 'prob'
    end_date : str, optional
        End date, by default END_DATE

    Returns
    -------
    bool
        Indicates if there will be a play button on the time slider
    dash.dcc.Slider.Slider
        Time slider
    """

    ts_dict = gen_ts_marks(ts_type, end_date)

    ts_min = ts_dict['min']
    ts_max = ts_dict['max']
    ts_step = ts_dict['step']
    ts_play = ts_dict['play']
    ts_marks = ts_dict['marks']

    marks = {
            tstep: {'label': ts_marks[tstep]}
        for tstep in ts_marks
        }

    logging.debug("FCST MARKS %s", marks[list(marks.keys())[-1]])
    if ts_type in ('prob', 'was'):
        marks[list(marks.keys())[-1]]['style'] = {}
        marks[list(marks.keys())[-1]]['style']['left'] = ''
        marks[list(marks.keys())[-1]]['style']['right'] = '-40px'

    return ts_play, dcc.Slider(
            id=f'{ts_type}-slider-graph',
            min=ts_min, max=ts_max, step=ts_step, value=ts_min,
            marks=marks
            )


def gen_time_bar(ts_type='prob', start_date=START_DATE, end_date=END_DATE):
    """ Generate time bar according to the section

    Parameters
    ----------
    ts_type : str, optional
        Time slider type, by default 'prob'
    start_date : str, optional
        Start date, by default START_DATE
    end_date : str, optional
        End date, by default END_DATE

    Returns
    -------
    dash.html.Div.Div
        Time bar
    """

    date_picker = html.Span([
        dcc.DatePickerSingle(
            id=f'{ts_type}-date-picker',
            min_date_allowed=dt.strptime(start_date, "%Y%m%d"),
            max_date_allowed=dt.strptime(end_date, "%Y%m%d"),
            initial_visible_month=dt.strptime(end_date, "%Y%m%d"),
            display_format='DD MMM YYYY',
            date=end_date,
            # clearable=True,
            placeholder='DD MON YYYY',
            # reopen_calendar_on_clear=True,
            ),
        dbc.Button(
            id='clear_button'
            )],
        className="timesliderline",
        )

    play_button = html.Span(
        children=[
            html.Button(title='Play',
                        id='btn-play', n_clicks=0,
                        className='fa fa-play text-center'),
            ],
            className="timesliderline anim-buttons",
        )

    ts_play, ts_content = gen_time_slider(ts_type, end_date)
    time_slider = html.Span(
        ts_content,
        id=f'{ts_type}-slider-container',
        className="timesliderline",
        )

    logging.debug("TIME SLIDER %s", time_slider)

    if ts_play:
        return html.Div([
            date_picker,
            play_button,
            time_slider
            ],
            className="timeslider"
        )

    return html.Div([
        date_picker,
        time_slider
        ],
        className="timeslider"
    )


def models_children(start_date=START_DATE, end_date=END_DATE):
    """ Return the html for models maps

    Parameters
    ----------
    start_date : str, optional
        Start date, by default START_DATE
    end_date : str, optional
        End date, by default END_DATE

    Returns
    -------
    list
        Forecast tab elements
    """

    return [
            html.Div(
                id=dict(
                    tag='tab-name',
                    index='models',
                    )
                ),
            dbc.Alert(
                "To explore the forecast, please select a variable and click on APPLY.",
                id="alert-forecast",
                is_open=True,
                duration=6000,
                fade=True,
                color="primary",
                style={ 'overflow': 'auto', 'marginBottom': 0 }
                ),
            html.Div(
                id='div-collection',
    #            children=[dbc.Spinner(
    #            id='loading-graph-collection',
    #            show_initially=False,
                children=[
                    dbc.Container(
                        id='graph-collection',
                        children=[
                        ],
                        fluid=True,
                        ),
                    html.Div(DISCLAIMER_MODELS,
                             className='disclaimer'),
                   ]
    #            )],
            ),
            html.Div(
                [dcc.Store(id="model-clicked-coords"),
                 dcc.Store(id="current-popups-stored")]
            ),
            html.Div(
                dcc.Interval(id='slider-interval',
                    interval=1000,
                    n_intervals=0,
                    disabled=True
            )),
            dbc.NavbarSimple([
                html.Div([
                    gen_time_bar('model', start_date=start_date, end_date=end_date),
                    layout_view(),
                    timeseries(),
                    # layout_layers(),
                    ],
                         id='layout-dropdown',
                         className="layout-dropdown",
                         ),
                    ],
                    className='fixed-bottom navbar-timebar',
                    fluid=True,
                    expand='lg',
                    dark=True,
                    fixed='bottom',
                )
            ]


def alert_3day_update():
    """ Create the alert to notify users that after April, 3 days of forecast is now
        available for PROB and WAS maps

    Returns
    -------
    dash_bootstrap_components._components.Toast.Toast
        Alert
    """

    if DELAY_DATE:
        date = dt.strptime(DELAY_DATE, "%Y%m%d").strftime("%b %d %Y")
        message = "3 day forecast available starting {}".format(date)
        return dbc.Toast(
                [html.P(message, className="mb1"),
                 html.I(
                     className="fa fa-solid fa-caret-down",
                     )],
                 id="toast",
                 header=None,
                 icon="warning",
                 duration=10000,
                 dismissable=True,
                 )
    return


def prob_children(start_date=START_DATE, end_date=END_DATE):
    """ Return html for probablility maps

    Parameters
    ----------
    start_date : str, optional
        Start date, by default START_DATE
    end_date : str, optional
        End date, by default END_DATE

    Returns
    -------
    list
        Probability tab elements
    """

    return [
            html.Div(
                id=dict(
                    tag='tab-name',
                    index='prob',
                    )
                ),
            html.Div(
                id='prob-graph',
                className='graph-with-slider'),
            alert_3day_update(), 
            html.Div(DISCLAIMER_MODELS,
                     className='disclaimer'),
            dbc.NavbarSimple([
                html.Div([
                    gen_time_bar('prob', start_date=start_date, end_date=end_date),
                    layout_view(),
                    ],
                         id='layout-dropdown',
                         className="layout-dropdown",
                         ),
                    ],
                    className='fixed-bottom navbar-timebar',
                    fluid=True,
                    expand='lg',
                    dark=True,
                    fixed='bottom',
                )
            ]


def was_children(start_date=START_DATE, end_date=END_DATE):
    """ Return html for WAS maps

    Parameters
    ----------
    start_date : str, optional
        Start date, by default START_DATE
    end_date : str, optional
        End date, by default END_DATE

    Returns
    -------
    list
        WAS tab elements
    """

    return [
            html.Div(
                id=dict(
                    tag='tab-name',
                    index='was',
                    )
                ),
            dbc.Spinner(
                html.Div(
                    children=[
                        html.Div(
                            id="{'index':'None', 'tag': 'empty-map'}")
                        ],
                    id='was-graph',
                    className='graph-with-slider'),
                ),
            alert_3day_update(), 
            html.Div(DISCLAIMER_MODELS,
                     className='disclaimer'),
            dbc.NavbarSimple([
                html.Div([
                    gen_time_bar('was', start_date=start_date, end_date=end_date),
                    layout_view(),
                    ],
                         id='layout-dropdown',
                         className="layout-dropdown",
                         ),
                    ],
                    className='fixed-bottom navbar-timebar',
                    fluid=True,
                    expand='lg',
                    dark=True,
                    fixed='bottom',
                )
            ]


def tab_forecast(window='models', start_date=START_DATE, end_date=END_DATE):
    """ The MAIN function to return all appropriate html for selected tab and sidebar selection

    Parameters
    ----------
    window : str, optional
        Window name, by default 'models'
    start_date : str, optional
        Start date, by default START_DATE
    end_date : str, optional
        End date, by default END_DATE

    Returns
    -------
    dash.dcc.Tab.Tab
        Forecast tab
    """

    windows = {
            'models': models_children(start_date=start_date, end_date=end_date),
            'was': was_children(start_date=start_date, end_date=end_date),
            'prob': prob_children(start_date=start_date, end_date=end_date),
            }

    return dcc.Tab(label='Forecast',
                   id='forecast-tab',
                   value='forecast-tab',
                   className='horizontal-menu',
                   children=windows[window],
                   )


def expand_dropdown(window):
    """ Build a dictionary to return appropriate expanded sidebar dropdown

    Parameters
    ----------
    window : str
        Window name

    Returns
    -------
    dict
        Dropdown items with their corresponding expansions
    """

    expand_dropdown_dict = {
            'models': False, 
            'prob': False, 
            'was': False 
            }
    expand_dropdown_dict[window] = True

    return expand_dropdown_dict


def sidebar_forecast(variables, default_var, models, default_model, window='models',
                     country='burkinafaso'):
    """ Build forecast sidebar

    Parameters
    ----------
    variables : list
        Variable names
    default_var : str
        Default variable name
    models : list
        Model names
    default_model : str
        Default model name
    window : str, optional
        Window name, by default 'models'
    country : str
        Country name

    Returns
    -------
    list
        Forecast sidebar elements
    """

    # Get which sidebar dropdown should be expanded for complex url search
    dropdown = expand_dropdown(window)

    return [
        html.Div([
            html.Label("Variable"),
            dcc.Dropdown(
                id='variable-dropdown-forecast',
                options=[{'label': variables[variable]['name_sidebar'],
                        'value': variable} for variable in variables],
                value=default_var,
                clearable=False,
                searchable=False,
                optionHeight=50,
                maxHeight=400
            )],
            className="sidebar-first-item",
        ),
        html.Div([
            dbc.Card([
                dbc.CardHeader(html.H2(
                    dbc.Button(children=["Models",
                        html.Span(
                            html.I(className='fa fa-solid fa-angle-up'),
                            id={'type':'caret', 'index':1}, className="caret-span")
                        ],
                        color="link", id='group-1-toggle', className='dropdown'),
                )),
                dbc.Collapse(
                    id={'type':'collapse', 'index':1},
                    is_open=dropdown['models'],
                    children=[
                        dbc.CardBody([
                            dbc.Checklist(
                                id='model-dropdown',
                                options=[{'label': models[model]['name'],
                                        'value': model} for model in models],
                                #value=[default_model,],
                                value=default_model,
                                class_name="sidebar-dropdown",
                            ),
                            html.Span([
                                html.Button('APPLY', id='models-apply', n_clicks=0),
                            ]),
                            #add hidden country fields and  button for gifs over entered coords
                            html.Span([
                                dcc.Input(id="country-zoom", type="text", style={'display':'none'}),
                    dcc.Input(id="country-lat", type="text", style={'display':'none'}),
                                dcc.Input(id="country-lon", type="text", style={'display':'none'}),
                                html.Button(id="country-focus", n_clicks=0, style={'display':'none'}),
                            ])
                            ],
                        )
                    ]
                )],
            ),
            dbc.Card([
                dbc.CardHeader(html.H2(
                    dbc.Button(children=["Probability of exceedance",
                        html.Span(
                            html.I(className='fa fa-solid fa-angle-up'),
                            id={'type':'caret', 'index':2}, className="caret-span-closed")
                        ],
                        color="link", id='group-2-toggle', className='dropdown'),
                )),
                dbc.Collapse(
                    id={'type':'collapse', 'index':2},
                    is_open=dropdown['prob'],
                    children=[
                        dbc.CardBody([
                            dcc.RadioItems(
                                id='prob-dropdown',
                                options=[],
                                value=None,
                                className="sidebar-dropdown"
                            ),
                            html.Span([
                                html.Button('APPLY', id='prob-apply', n_clicks=0),
                            ]
                            )]
                        )
                    ]
                )],
            ),
            dbc.Card([
                dbc.CardHeader(html.H2(
                    dbc.Button(children=["Warning Advisory System",
                                        html.Span(
                                            html.I(className='fa fa-solid fa-angle-up'),
                                            id={'type':'caret', 'index':3},
                                            className="caret-span-closed")],
                            color="link", id='group-3-toggle', className='dropdown',
                            disabled=False)
                    )),
                dbc.Collapse(
                    id={'type':'collapse', 'index': 3},
                    # id='collapse-3',
                    is_open=dropdown['was'],
                    children=[
                        dbc.CardBody([
                            dcc.RadioItems(
                                id='was-dropdown',
                                options=[{'label': WAS[was]['name'],
                                        'value': was} for was in WAS],
                                value=country,
                                className="sidebar-dropdown"
                                ),
                            html.Div(
                                dcc.Store(id="was-previous"),
                                ),
                            html.Span([
                                html.Button('APPLY', id='was-apply', n_clicks=0),
                                ]
                                    )]
                                    )
                        ]
                    )],
                    ),
        ],
        className="accordion"
        ),
        html.Div([
            dbc.Row([
                dbc.Col(
                    dbc.Button("", id="info-button"),
                    width=3,
                    ),
                dbc.Col(
                    dbc.Button("DOWNLOAD", id="download-button"),
                    width=9,
                    ),
                ],
                # no_gutters is replaced with the className because of bootstrap update
                # no_gutters=True,
                className='g-0',
            ),
            dbc.Row([
                dbc.Col([
                    dbc.Collapse(
                        dbc.Card(dbc.CardBody(
                            [
                                dbc.Button('USER GUIDE',
                                        id='btn-userguide-download',
                                        n_clicks=0,
                                        href=PATHS['user_guide'],
                                        className='download-section',
                                        ),
                                html.P("""Please check out the User Guide for more information."""),
                                ],
                            className="card-text",
                            )),
                        id="info-collapse",
                        is_open=False,
                        ),
                    dbc.Collapse(
                        dbc.Card(dbc.CardBody(
                            [
                                html.Label("CURRENT SELECTION"),
                                dbc.Button('PNG FRAME',
                                        id='btn-frame-download',
                                        n_clicks=0,
                                        href="#",
                                        className='download-section',
                                        ),
                                # dbc.Spinner(
                                    dcc.Download(
                                        id="frame-download",
                                        base64=True,
                                        ),
                                    #  ),
                                dbc.Button('GIF ANIM',
                                        id='btn-anim-download',
                                        n_clicks=0,
                                        href="#",
                                        external_link=True,
                                        target="_blank",
                                        className='download-section',
                                        ),
                                html.Label("NUMERICAL DATA"),
                                dbc.Button('NETCDF',
                                        id='btn-netcdf-download',
                                        n_clicks=0,
                                        href= PATHS['netcdf'],
                                        external_link=True,
                                        target="_blank",
                                        className='download-section',
                                        ),
                        ],
                        className="card-text",
                        )),
                    id="download-collapse",
                    is_open=False,
                )
                ]),
            ],
            className="collapsible-cards",
            ),
        ],
        className="sidebar-bottom",
        )
    ]


def get_view(index, url, attr):
    """ Helper function to assign selected map with selected view 

    Parameters
    ----------
    index : int
        _description_
    url : list
        URL of selected tile
    attr : list
        Attributes of selected tile

    Returns
    -------
    list
        URL of selected tile for Models section
    list
        Attributes of selected tile for Models section
    list
        URL of selected tile for Probability of exceedance section
    list
        Attributes of selected tile for Probability of exceedance section
    list
        URL of selected tile for Warning Advisory System section
    list
        Attributes of selected tile for Warning Advisory System section
    """

    mod_url = mod_attr = []
    prob_url = prob_attr = []
    was_url = was_attr = []
    if index == 1:
        mod_url = url
        mod_attr = attr
    if index == 2:
        prob_url = url 
        prob_attr = attr
    if index == 3:
        was_url = url 
        was_attr = attr

    return mod_url, mod_attr, prob_url, prob_attr, was_url, was_attr
