import pandas as pd
import dash
import dash_bootstrap_components as dbc
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import DbAccess as db
import Params
import plotly.express as px
from datetime import datetime, timedelta
import time
import plotly.graph_objects as go
from dash.dependencies import ClientsideFunction, Input, Output #per fer funcions js a client
import os
import math

#MAX_LATITUDE=41.4803
#MIN_LATITUDE=41.4659
#MAX_LONGITUDE=2.0699
#MIN_LONGITUDE=2.0415
MAX_ITEMS_SELECTED=5
MIN_MINUTES=5
MAX_MINUTES=120
MAX_TEXT_SIZE=20
COLOR_SERIE='fuchsia'
COLOR_USR='green'
CNST_ZOOM=10

#Template Blootstrap
external_stylesheets = [dbc.themes.CYBORG] # [https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

# Get path of the current dir, then use it to create paths:
CURRENT_DIR = os.path.dirname(__file__)
MapBoxToken = open(os.path.join(CURRENT_DIR, 'resources/mapbox_token.txt')).read()

#Funció que determina el zoom
def calcZoom(minLat,maxLat, minLong, maxLong):
    yWidth=maxLat-minLat
    xWidth=maxLong-minLong
    yZoom=-1.446*math.log(yWidth)+7.2753
    xZoom=-1.415*math.log(yWidth)+8.7068
    #yZoom=CNST_ZOOM
    #xZoom=CNST_ZOOM
    return min(round(yZoom,2),round(xZoom,2))

_MyDb=db.BabyTrackerDB(Params.DB_USER, Params.DB_PASS, Params.DB_SERVER, Params.DB_DATABASE, Params.DB_PORT)
mydfTracks=_MyDb.GetTracks(1)

#mydfTracksA=_MyDb.GetTracks(1,2,datetime.strptime('03/01/2021','%d/%m/%Y'))
#Dibuixem el mapa base amb la posició de l'usuari
if mydfTracks is None:
    fig = go.Figure(go.Scattermapbox(
        mode = "markers+text",
        marker =dict(size=20, color='red'),
        textposition='top right',
        name='Basic')
    )
    fig.update_layout(
    margin ={'l':0,'t':0,'b':0,'r':0},
    height=750,
    mapbox = {
        'accesstoken':MapBoxToken,
        'style': 'stamen-watercolor',
        'zoom': CNST_ZOOM},
    title_text='Cercador de Babys')
else:    
    fig = go.Figure(go.Scattermapbox(
        mode = "markers+text",
        lon =mydfTracks,
        lat = mydfTracks,
        marker =dict(size=20, color='red'),
        textposition='top right',
        text=mydfTracks.LocDate,
        name='Basic')
    )

    fig.update_layout(
    margin ={'l':0,'t':0,'b':0,'r':0},
    height=750,
    mapbox = {
        'center': {'lon':(mydfTracks['Longitude'].min()+mydfTracks['Longitude'].max())/2, 'lat': (mydfTracks['Latitude'].min()+mydfTracks['Latitude'].max())/2},
        'accesstoken':MapBoxToken,
        'style': 'stamen-watercolor',
        'zoom':CNST_ZOOM        
        },
    title_text='Cercador de Babys')

cap=dbc.Jumbotron(fluid=True, className="pt-2 pb-2", children=[
    dbc.Row(children=[
		    html.H4("Benvingut!! Has perdut els babys???, Tranquil els trobarem!" )
		    ],  justify="center", align="center"),
])
app.layout=html.Div(children=[
	cap,
    dbc.Row(children=[
            dbc.Col(width=1),
            dbc.Col(className="aborder border-primary", width=4,  children=[
                 html.Div([
                    'Tipus de Mapa',
                    dcc.Dropdown(
                    id='idTipusMap',
                    options=[{'label': i, 'value': i} for i in ["basic","dark","light","outdoors","satellite","satellite-streets","stamen-terrain","stamen-watercolor","streets"]],
                    value='stamen-watercolor',
                    clearable=False
                    ),    
                 ])
            ]),
             dbc.Col(className="aborder border-primary", width=6, children=[
                html.Div([
                    dbc.Button("Actualitza", id="idButton", className="mr-2"),
                    html.Span(id="idOutput", style={"vertical-align": "middle"}),
                    html.Span(id="idLocation", style={"vertical-align": "middle"}),
                    html.Span("hola Bola", id="idOutputClient", style={"vertical-align": "middle"})
                ]) 
          ]),
          dbc.Col(width=1),
        ]),
    dbc.Row(children=[
        dbc.Col(width=1),
        dbc.Col(width=10, children=[
            html.Div([
                   'Seleccionar últims minuts',
                   dcc.Slider(
                        id='idSlider',                        
                        min=MIN_MINUTES,
                        max=MAX_MINUTES,
                       step=None,
                        marks={str(i):{'label':str(i)+'m'} for i in range(5,MAX_MINUTES+5,5)},
                        value=5                        
                    )
                ],style={'height':75})
            ]),
        dbc.Col(width=1),
        ]),
    dbc.Row(children=[
        dbc.Col(width=1),
        dbc.Col(className="aborder border-primary", width=10, children=[
            dcc.Graph(id='idBabyShowMap', figure=fig),
            dcc.Interval(
                id='interval-component',
                interval=30*1000, # in milliseconds (30s)
                n_intervals=0)
        ]),
        dbc.Col(width=1),
    ])
])

##actualitem dataframe de la bbdd
#@app.callback(
#    Output("idBabyShowMap", "figure"),
#    Input("idButton","n_clicks")
#)
#def update_sqlDataframe(bActualitza):
#    df=_MyDb.GetTracks(1)
#    updateDades(df)
#    return(mydfTracks2)

#dibuixem tot el mapa amb el que es necessita. tipus de mapa, loc de l'usuari i llista de punts del esp32
@app.callback(
    Output("idLocation", "children"), 
    Output("idBabyShowMap", "figure"),
    Input("idTipusMap","value"),
    Input("idSlider","value"),
    Input("idOutputClient", "children"),
    Input("idButton","n_clicks")
)
def update_MapTotal(TipusMap, TempsSelected, geolocationUser, n):
    """lala"""
    mydfTracks=_MyDb.GetTracks(1)
    if mydfTracks is None:
        fig = go.Figure(go.Scattermapbox(
            mode = "markers+text",
            marker =dict(size=20, color='red'),
            textposition='top right',
            name='Basic')
        )
        fig.update_layout(
        margin ={'l':0,'t':0,'b':0,'r':0},
        height=750,
        mapbox = {
            'accesstoken':MapBoxToken,
            'style': TipusMap},
        title_text='Cercador de Babys')
        return "DB error", fig

    DateHour=datetime.now()+timedelta(minutes=-TempsSelected*10)
    dfSelected=mydfTracks[mydfTracks['LocDate']>=DateHour]
    if dfSelected.empty:
        dfSelected=mydfTracks.head(MAX_ITEMS_SELECTED)

    fig = go.Figure(go.Scattermapbox(
        mode = "markers+lines+text",
        lon = dfSelected.Longitude,
        lat = dfSelected.Latitude,
        textposition='top right',
        textfont=dict(size=MAX_TEXT_SIZE, color=COLOR_SERIE),
        text=dfSelected['LocDate'].dt.strftime('%H:%M:%S'),
        marker = {'size': 10, 'color':COLOR_SERIE},
        name='Trackers')
    )
     #si tenim la geocalització de l'usuari, la pintem i posicionem el mapa al centre entre la usr location y els tracks
    maxLatitude=mydfTracks['Latitude'].max()
    maxLongitude=mydfTracks['Longitude'].max()
    minLatitude=mydfTracks['Latitude'].min()
    minLongitude=mydfTracks['Longitude'].min()

    myloc=geolocationUser.split(",")
    if (len(myloc)==2):   
        fig.add_trace(go.Scattermapbox(
            mode = "markers+lines",
            lon =[myloc[1]],
            lat = [myloc[0]],
            textposition='top right',
            textfont=dict(size=MAX_TEXT_SIZE, color=COLOR_USR),
            text="MyLoc" + str(datetime.now()),
            marker =dict(size=20, color='green'),
            name='MyLoc')
        )
        maxLatitude=max(float(myloc[0]),maxLatitude)
        maxLongitude=max(float(myloc[1]),maxLongitude)
        minLatitude=min(float(myloc[0]),minLatitude)
        minLongitude=min(float(myloc[1]),minLongitude)
    
    fig.update_layout(
    margin ={'l':0,'t':0,'b':0,'r':0},
    height=750,
    mapbox = {
        'center': {'lon':(minLongitude+maxLongitude)/2, 'lat': (minLatitude+maxLatitude)/2},
        'accesstoken':MapBoxToken,
        'style': TipusMap,
        'zoom':calcZoom(minLongitude,maxLongitude,minLatitude,maxLatitude)}
    )
    #mydfTracks=_MyDb.GetTracks(1,HourValue)
    #fig = go.Figure(go.Scattermapbox(
    #    mode = "markers+lines",
    #    lon = mydfTracks.Longitude,
    #    lat = mydfTracks.Latitude,
    #    marker = {'size': 10, 'color':'fuchsia'},
    #    name='DadUpdated'))
    #fig.update_layout(
    #    margin ={'l':0,'t':0,'b':0,'r':0},
    #    height=750,
    #    mapbox = {
    #        'center': {'lon':(MIN_LONGITUDE+MAX_LONGITUDE)/2, 'lat': (MIN_LATITUDE+MAX_LATITUDE)/2},
    #        'style': "stamen-terrain",
    #        'zoom': CNST_ZOOM},
    #    title_text='Cercador de Babys')
    return  f" --Slider SELECT: {TempsSelected} -- GEOLOCATION: {myloc} --",fig


#funció que s'executa en client al navegador i obté les coordenades gps de l'usuari
app.clientside_callback(
    """
    function(TipusMap, valueSlider) {
        if(typeof(window.miPos)=='undefined')
            window.miPos="Obtaining Geolocation....";

        function miFunc(posi) {window.miPos=posi.coords.latitude + "," + posi.coords.longitude;}

        if (navigator.geolocation) {
            objPosition=navigator.geolocation.getCurrentPosition(miFunc);
            return(window.miPos);
        } 
        else {
            return "Geolocation is not supported by this browser.";
        }
    }
    """,
    Output("idOutputClient", "children"),
    Input("idTipusMap","value"),
    Input("idSlider","value")
)

if __name__ == '__main__':
	#app.run_server(ssl_context='adhoc',debug=True, use_reloader=False,host='0.0.0.0', port=8017)
    app.run_server(debug=True, use_reloader=True,host='0.0.0.0', port=8018)
