#! /usr/bin/python
# -*- coding: utf-8 -*-

try:
    from dash import Dash
    from dash.dependencies import Input, Output, State
    import dash_core_components as dcc
    import dash_html_components as html
    import plotly.graph_objs as go
except:
    raise ImportError("You need to install 'dash', 'dash_core_components' and 'dash_html_components'")

import numpy as np
from nenupy import BST
import glob
import os


# ================================================================================ #
# ------------------------------------ GLOBAL ------------------------------------ #
# ================================================================================ #
ymin = -1
ymax = -1
prev_o = -1
prev_f = -1
prev_a = -1
prev_d = -1
# ================================================================================ #
# ================================================================================ #


# ================================================================================ #
# ------------------------------------ LAYOUT ------------------------------------ #
# ================================================================================ #
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = Dash(__name__, external_stylesheets=external_stylesheets)

app.layout = html.Div([

    html.H3('BST plotting interface'),

    html.Div([
        dcc.Input(id='upload-folder',
            value='{}'.format(os.getcwd()),
            type='text',
            style={'width': 750}),
        html.Button(id='submit-button',
            type='submit',
            children='Submit'),
        ], style={'margin-bottom': 20}),

    html.P('Filename:'),

    html.Div(id='filename-dropdown-env',
        children=[
            dcc.Dropdown(id='filename-dropdown')
            ]
        ),
    html.Div(id='current-file', style={'opacity': 0}),

    dcc.Graph(id='main-graph'),
    
    html.P(children='Frequency (MHz):'),
    
    html.Div(id='freq-slider-env',
        children=[
            dcc.Slider(id='freq-slider'),
            ], style={'margin-bottom': 40}),

    html.Div([
        html.Div([
            html.P('Analogical beam:'),
            html.Div(id='abeam-dropdown-env',
                children=[
                    dcc.Dropdown(
                        id='abeam-selector'),
                    ])
            ], className="six columns"),

        html.Div([
            html.P('Numerical beam:'),
            html.Div(id='dbeam-dropdown-env',
                children=[
                    dcc.Dropdown(
                        id='dbeam-selector'),
                    ])
            ], className="six columns"),
        ], className="row")

    ])
# ================================================================================ #
# ================================================================================ #



# ================================================================================ #
# ------------------------------- FOLDER SELECTION ------------------------------- #
# ================================================================================ #
@app.callback(
    Output('filename-dropdown-env', 'children'),
    [Input('submit-button', 'n_clicks')],
    [State('upload-folder', 'value')])
def data_folder_selection(clicks, folder):
    bst_files = glob.glob( os.path.join(folder, '*BST.fits') )

    if (folder is None) or (not os.path.isdir(folder)) or (len(bst_files)==0):
        bst_files=[]
        return dcc.Dropdown(
                id='filename-dropdown',
                options=[{'label': '', 'value': None}],
                value=''
            )

    return dcc.Dropdown(
            id='filename-dropdown',
            options=[{'label': fi, 'value': fi} for fi in bst_files],
            value=None # bst_files[0]
        )
# ================================================================================ #
# ================================================================================ #



# ================================================================================ #
# ----------------------------------- LOAD FILE ---------------------------------- #
# ================================================================================ #
@app.callback(
    Output('current-file', 'children'),
    [Input('filename-dropdown', 'value')])
def load_bst(selected_file):
    if (selected_file is not None) & (selected_file != ''):
        global bst
        bst = BST(selected_file)
    return selected_file
# ================================================================================ #
# ================================================================================ #



# ================================================================================ #
# -------------------------------- ABEAM SELECTION ------------------------------- #
# ================================================================================ #
@app.callback(
    Output('abeam-dropdown-env', 'children'),
    [Input('current-file', 'children')])
def abeam_dropdown(selected_file):
    if (selected_file is None) or (selected_file==''):
        return dcc.Dropdown(
                id='abeam-selector',
                options=[{'label': fi, 'value': fi} for fi in range(1)],
                value=0
            )

    return dcc.Dropdown(
            id='abeam-selector',
            options=[{'label': fi, 'value': fi} for fi in bst.abeams],
            value=bst.abeam
        )
# ================================================================================ #
# ================================================================================ #



# ================================================================================ #
# ---------------------------------- FREQ SLIDER --------------------------------- #
# ================================================================================ #
@app.callback(
    Output('freq-slider-env', 'children'),
    [Input('current-file', 'children')])
def freq_slider(selected_file):
    if (selected_file is None) or (selected_file==''):
        return dcc.Slider(
                id='freq-slider',
                min=0,
                max=10,
                value=0,
                updatemode='drag',
                step=1,
                marks={str(i): str(i) for i in range(10)}
            )

    freqs = bst._freqs[0][bst._freqs[0] != 0]
    df = freqs[1] - freqs[0]
    f_marks = [''] * freqs.size
    prev_f = -100
    i = 0
    for f in freqs:
        if f - prev_f > 20 * df:
            f_marks[i] = '{:.2f}'.format(f)
            prev_f = f
        i += 1

    return dcc.Slider(
            id='freq-slider',
            min=bst.freqmin,
            max=bst.freqmax,
            value=bst.freqmin,
            updatemode='drag',
            step=df,
            marks={str(freq): mark for freq, mark in zip(freqs, f_marks)}
        )
# ================================================================================ #
# ================================================================================ #



# ================================================================================ #
# -------------------------------- DBEAM SELECTION ------------------------------- #
# ================================================================================ #
@app.callback(
    Output('dbeam-dropdown-env', 'children'),
    [Input('current-file', 'children')])
def dbeam_dropdwon(selected_file):
    if (selected_file is None) or (selected_file == ''):
        return dcc.Dropdown(
            id='dbeam-selector',
            options=[{'label': fi, 'value': fi} for fi in range(1)],
            value=0
            )

    return dcc.Dropdown(
        id='dbeam-selector',
        options=[{'label': fi, 'value': fi} for fi in bst.dbeams],
        value=bst.dbeam
        )
# ================================================================================ #
# ================================================================================ #



# ================================================================================ #
# --------------------------------- FIGURE UPDATE -------------------------------- #
# ================================================================================ #
@app.callback(
    Output('main-graph', 'figure'),
    [Input('current-file', 'children'),
    Input('freq-slider', 'value'),
    Input('abeam-selector', 'value'),
    Input('dbeam-selector', 'value')])
def update_figure(filename, selected_freq, abeam, dbeam):
    if (filename is None) or (filename == '') or (selected_freq==0):
        return {
            'data': go.Scatter(
                x=np.arange(10),
                y=np.zeros(10),
                mode='lines',
                opacity=0.7,
                name=''
            ),
            'layout': go.Layout(
                xaxis={'title': 'Time'},
                yaxis={'title': 'Amplitude'},
                margin={'l': 80, 'b': 40, 't': 40, 'r': 10},
                legend={'x': 1, 'y': 0.9},
                title='',
                hovermode='closest'
            )
        }

    traces = []
    ymin   = []
    ymax   = []
    for p in bst._pols:
        bst.select(freq=selected_freq, polar=p, abeam=abeam, dbeam=dbeam)
        traces.append(go.Scatter(
            x=(bst.data['time'] - bst.data['time'][0]).sec / 60.,
            y=bst.data['amp'],
            mode='lines',
            opacity=0.7,
            name=p
        ))
        ymin.append( bst.data['amp'].min() )
        ymax.append( bst.data['amp'].max() )
    ymin = np.min(ymin)
    ymax = np.max(ymax)
    dy = ymax - ymin
    ymin = ymin - 0.1*dy
    ymax = ymax + 0.1*dy

    return {
        'data': traces,
        'layout': go.Layout(
            xaxis={'title': 'Time since {} (min)'.format(bst.data['time'][0].iso)},
            yaxis={'title': 'Amplitude', 'range': [ymin, ymax]},
            margin={'l': 80, 'b': 40, 't': 40, 'r': 10},
            legend={'x': 1, 'y': 0.9},
            title='{} MHz'.format(bst.freq),
            hovermode='closest'
        )
    }
# ================================================================================ #
# ================================================================================ #



if __name__ == '__main__':
    app.run_server(debug=True)