"""Punto di ingresso del frontend Brython: accesso, layout, navigazione."""
from browser import document, window

import api
import i18n
import state
import ui
import views_admin
import views_home
import views_login
import views_plans
import views_profile
import views_registry
import views_schedule
import views_shifts
import views_workers
from i18n import t
from ui import E

VIEWS = {
    "home": views_home.render,
    "piani": views_plans.render,
    "turni": views_schedule.render,
    "report": views_schedule.render_report,
    "lavoratori": views_workers.render,
    "anagrafiche": views_registry.render,
    "operativita": views_shifts.render,
    "profilo": views_profile.render,
    "admin": views_admin.render,
}


# il gruppo riservato all'amministratore: si confronta per identita', non per
# etichetta, che cambia con la lingua
PIATTAFORMA = object()


def routes():
    """Voci del menu: le etichette seguono il dizionario dell'ente in uso."""
    T = state.term
    return [
        (t("Pianificazione"), [
            ("home", t("Cruscotto")),
            ("piani", t("Periodi e {giri}", giri=T("round", plurale=True))),
            ("turni", t("Calendario {turni}", turni=T("shift", plurale=True))),
            ("report", t("Report")),
        ]),
        (t("Configurazione"), [
            ("lavoratori", t("{lavoratori} e regole",
                             lavoratori=T("worker", plurale=True, maiuscola=True))),
            ("anagrafiche", t("{stanze} e {specialita}",
                              stanze=T("room", plurale=True, maiuscola=True),
                              specialita=T("specialty", plurale=True))),
            ("operativita", t("Operatività")),
        ]),
        (t("Il mio spazio"), [
            ("profilo", t("Profilo e diario")),
        ]),
        (PIATTAFORMA, [
            ("admin", t("Enti e account")),
        ]),
    ]


def _change_org(event):
    """Cambia l'ente su cui si sta lavorando e ricarica i dati."""
    org_id = int(event.target.value)
    state.CURRENT["plan_id"] = None
    api.post(f"/orgs/{org_id}/select", {}, lambda _: state.reload(render))


def _org_selector():
    orgs = state.AUTH.get("organizations", [])
    if len(orgs) <= 1:
        nome = orgs[0]["name"] if orgs else t("nessun ente")
        return E("div", nome, cls="org-current")
    scelta = E("select", onchange=_change_org, cls="org-select")
    for org in orgs:
        opzione = E("option", org["name"], value=str(org["id"]))
        if org["id"] == state.AUTH.get("org_id"):
            opzione.selected = True
        scelta <= opzione
    return scelta


def _change_password():
    attuale = E("input", type="password")
    nuova = E("input", type="password")
    esito = E("div", cls="login-error")

    def salva():
        api.post("/auth/change-password", {"current": attuale.value, "new": nuova.value},
                 lambda _: (ui.toast(t("Password aggiornata: rientra con quella nuova"), "ok"),
                            window.location.reload()),
                 lambda msg: setattr(esito, "text", msg))
        return False        # la modale resta aperta finché il server non conferma

    ui.modal(t("Cambia password"),
             E("div",
               E("div", E("label", t("Password attuale")), attuale, cls="field"),
               E("div", E("label", t("Nuova password")), nuova, cls="field"),
               esito),
             on_confirm=salva, confirm_label=t("Aggiorna"))


def _scegli_lingua(codice):
    """Cambia lingua e la registra fra le preferenze: lo segue su ogni computer."""
    i18n.ricorda(codice)
    api.put("/me/preferences", {"language": codice})
    i18n.carica(codice, lambda: state.reload(render))


def _logout():
    api.post("/auth/logout", {}, lambda _: window.location.reload())


def _sidebar():
    aside = E("aside", cls="sidebar")
    aside <= E("div", "RotaManager", E("small", t("gestione turni")), cls="brand")
    aside <= E("div", E("label", t("Ente")), _org_selector(), cls="org-box")
    nav = E("nav")
    for group, items in routes():
        if group is PIATTAFORMA and not state.is_admin():
            continue
        nav <= E("div", t("Piattaforma") if group is PIATTAFORMA else group,
                 cls="nav-group")
        for slug, label in items:
            nav <= E("a", label, href=f"#{slug}",
                     cls="active" if slug == state.CURRENT["route"] else None)
    nav <= E("div", t("Aiuto"), cls="nav-group")
    # il manuale è una pagina a sé servita dal backend: si apre in una scheda nuova
    # per non perdere il lavoro in corso nei form aperti
    nav <= E("a", t("Manuale d'uso"), href=f"/manuale?lang={i18n.lingua()}",
             target="_blank", rel="noopener")
    aside <= nav
    utente = state.user()
    aside <= E("div",
               E("div", utente.get("name") or utente.get("email", ""), cls="who"),
               E("div", utente.get("email", ""), cls="who-mail"),
               # senza nessun ente non si e' in sola lettura: non c'e' ancora nulla da leggere
               None if state.can_edit() or not state.AUTH.get("org_id")
               else ui.badge(t("sola lettura"), "warn"),
               ui.language_picker(_scegli_lingua),
               E("div",
                 ui.button(t("Password"), _change_password, cls="mini"),
                 ui.button(t("Esci"), _logout, cls="mini"),
                 cls="row-flex"),
               ui.made_by(scuro=True),
               cls="sidebar-foot")
    return aside


def render():
    root = document["root"]
    root.clear()
    root <= _sidebar()
    main = E("main")
    root <= main
    route = state.CURRENT["route"]
    if route == "admin" and not state.is_admin():
        route = "home"
    view = VIEWS.get(route, views_home.render)
    try:
        view(main)
    except Exception as exc:            # una vista rotta non deve lasciare la pagina vuota
        main <= E("div", E("h2", t("Errore nell'interfaccia")), E("pre", str(exc)),
                  cls="panel")
        raise


def show_login(message=None):
    document["root"].clear()
    views_login.render(document["root"], message)


def _on_hash(ev=None):
    route = window.location.hash[1:] or "home"
    if route != state.CURRENT["route"]:
        state.CURRENT["route"] = route
        if state.AUTH.get("user"):
            render()


def _start(sessione):
    """Decide cosa mostrare in base allo stato della sessione."""
    if not sessione or not sessione.get("authenticated"):
        show_login()
        return
    if not sessione.get("organizations"):
        if not sessione.get("user", {}).get("is_admin"):
            show_login(
                t("Nessun ente associato a questo account: contatta l'amministratore."))
            return
        # amministratore senza enti: si entra lo stesso, ma dalla pagina in cui
        # si creano gli enti e si attivano le richieste di registrazione
        state.CURRENT["route"] = "admin"
        state.reload(lambda: _con_lingua_scelta(render))
        return
    state.reload(lambda: _con_lingua_scelta(_apri))


def _apri():
    """Apre la schermata scelta nelle preferenze personali, se non se n'è chiesta un'altra."""
    if not window.location.hash:
        iniziale = state.preference("landing_route", "home")
        if iniziale in VIEWS:
            state.CURRENT["route"] = iniziale
    render()


def _con_lingua_scelta(poi):
    """Passa alla lingua registrata nel profilo, se e' diversa da quella in uso.

    Prima di autenticarsi si segue il browser; da qui in avanti comanda la
    preferenza personale, cosi' chi rientra da un altro computer ritrova
    l'applicazione come l'aveva lasciata.
    """
    scelta = state.preference("language", "")
    if scelta and scelta != i18n.lingua():
        i18n.ricorda(scelta)
        # non basta cambiare catalogo: il dizionario dell'ente («giro», «turno», …)
        # arriva dal server già tradotto nella lingua della *richiesta*, e quello
        # appena ricevuto è ancora nella lingua di partenza. Va richiesto di nuovo,
        # altrimenti si vede un menù mezzo francese e mezzo italiano.
        i18n.carica(scelta, lambda: state.reload(poi))
    else:
        poi()


def _avvia():
    """Parte solo a catalogo caricato: nessuna schermata compare mezza tradotta."""
    state.set_rerender(render)
    api.on_unauthorized = lambda: show_login(t("Sessione scaduta: accedi di nuovo."))
    window.addEventListener("hashchange", _on_hash)
    state.CURRENT["route"] = window.location.hash[1:] or "home"
    api.get("/auth/me", _start)


i18n.carica(i18n.iniziale(), _avvia)
