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

# AUTOMATICALLY MADE FILE. DO NOT EDIT.
# This file was generated by {{ author }} on {{ current_date }} with Python executable
# {{ sys_executable }}

import logging
import logging.config
import os
import threading
import datetime
from pathlib import Path, PosixPath, WindowsPath

from uuid import uuid4

from dash import html, dcc, Dash, Input, Output, callback, callback_context
import webviz_core_components as wcc
from flask_talisman import Talisman
import webviz_config
import webviz_config.plugins
from webviz_config.themes import installed_themes
from webviz_config.common_cache import CACHE
from webviz_config.webviz_store import WEBVIZ_STORAGE
from webviz_config.webviz_assets import WEBVIZ_ASSETS
from webviz_config.webviz_instance_info import WebvizRunMode, WEBVIZ_INSTANCE_INFO
from webviz_config.webviz_factory_registry import WEBVIZ_FACTORY_REGISTRY
from webviz_config.utils import deprecate_webviz_settings_attribute_in_dash_app

import webviz_core_components as wcc


# Start out by setting a sensible configuration for the root logger and setting a global 
# loglevel. The (global) loglevel defaults to WARNING, but can be set by the user via 
# the --loglevel argument. The call to basicConfig() should happen before any other logging 
# related calls, see https://docs.python.org/3/library/logging.html#logging.basicConfig
logging.basicConfig(level=logging.{{ loglevel }})

theme = webviz_config.WebvizConfigTheme("{{ theme_name }}")
theme.from_json((Path(__file__).resolve().parent / "theme_settings.json").read_text())

app = Dash(
    name=__name__,
    external_stylesheets=theme.external_stylesheets,
    assets_folder=Path("resources") / "assets",
    meta_tags=[
        {"name": "viewport", "content": "width=device-width, initial-scale=1"}
    ],
)

# For signing session cookies
# Use user provided environment variable if exists, otherwise generate fresh
app.server.secret_key = os.environ.get("WEBVIZ_SESSION_SECRET_KEY") or webviz_config.LocalhostToken.generate_token()

server = app.server

app.title = "{{ title }}"
app.config.suppress_callback_exceptions = True

# Dash is very eager to configure its own logger by both adding a handler and hardcoding
# the loglevel to INFO. Below we counteract both of these.
# We do not want to show INFO regarding werkzeug routing as that is too verbose.
app.logger.setLevel(logging.{{ loglevel }})
app.logger.handlers.clear()
logging.getLogger("werkzeug").setLevel(logging.WARNING)

{% if logging_config_dict is defined %}
# Apply a logging config dict (either full or incremental) as specified via the --logconfig
# command line argument. Note that unless the config dict contains 'incremental: True', the
# config in the dict will replace the existing logging configuration.
logging_config_dict = {{ logging_config_dict }}
print("Configuring logging from dictionary:", logging_config_dict)
logging.config.dictConfig(logging_config_dict)
{% endif %}

# Create the common webviz_setting object that will get passed as an
# argument to all plugins that request it.
webviz_settings: webviz_config.WebvizSettings = webviz_config.WebvizSettings(
    shared_settings=webviz_config.SHARED_SETTINGS_SUBSCRIPTIONS.transformed_settings(
        {{ shared_settings }}, {{ config_folder }}, {{ portable }} 
    ),
    theme=theme,
)

# Previously, webviz_settings was piggybacked onto the Dash application object.
# For a period of time, keep it but mark access to the webviz_settings attribute
# on the Dash application object as deprecated.
deprecate_webviz_settings_attribute_in_dash_app()
app._deprecated_webviz_settings = {
    "shared_settings" : webviz_settings.shared_settings,
    "theme" : webviz_settings.theme,
    "portable" : {{ portable }},
}

CACHE.init_app(server)

storage_folder = Path(__file__).resolve().parent / "resources" / "webviz_storage"

WEBVIZ_STORAGE.use_storage = {{portable}}
WEBVIZ_STORAGE.storage_folder = storage_folder

WEBVIZ_ASSETS.portable = {{ portable }}

run_mode = WebvizRunMode.PORTABLE if {{portable}} else WebvizRunMode.NON_PORTABLE
WEBVIZ_INSTANCE_INFO.initialize(
    dash_app=app,
    run_mode=run_mode,
    theme=theme,
    storage_folder=storage_folder
)

WEBVIZ_FACTORY_REGISTRY.initialize({{ internal_factory_settings if internal_factory_settings is defined else None }})

use_oauth2 = False

if {{ not portable }} and not webviz_config.is_reload_process():
    # When Dash/Flask is started on localhost with hot module reload activated,
    # we do not want the main process to call expensive component functions in
    # the layout tree, as the layout tree used on initialization will anyway be called
    # from the child/restart/reload process.
    app.layout = html.Div()
else:
    count_text_plugins = 0
    page_plugins = {}
    page_settings = {}
    {% for page in pageContents %}
    page_plugins["{{page.id}}"] = []
    page_settings["{{page.id}}"] = []
    {% for content_item in page.content -%}
    {% if content_item is string %}
    page_plugins["{{page.id}}"].append(wcc.WebvizPluginWrapper(id=f"text-{count_text_plugins}", views=[], initiallyActiveViewId="", name="Text", children=[dcc.Markdown(r"""{{ content_item }}""")]))
    count_text_plugins += 1
    {% else %}
    plugin = webviz_config.plugins.{{ content_item._call_signature[0] }}
    if not use_oauth2:
        use_oauth2 = plugin.oauth2 if hasattr(plugin, "oauth2") else use_oauth2

    page_plugins["{{page.id}}"].extend(plugin.{{ content_item._call_signature[1] }})
    page_settings["{{page.id}}"].extend([settings for settings in plugin.get_all_settings()])

    {% endif %}
    {% endfor %}
    {% endfor %}
    app.layout = html.Div(
        className="layoutWrapper", 
        children=[
            dcc.Location(id='location', refresh=True),
            wcc.WebvizContentManager(
                id="webviz-content-manager",
                children=[
                    wcc.Menu(
                        id="main-menu",
                        showLogo={{options.menu.show_logo}},
                        menuBarPosition="{{options.menu.bar_position}}",
                        menuDrawerPosition="{{options.menu.drawer_position}}",
                        initiallyPinned={{options.menu.initially_pinned}},
                        initiallyCollapsed={{options.menu.initially_collapsed}},
                        navigationItems={{navigation_items}},
                        {% if options.menu.homepage %}
                        homepageUrl="{{options.menu.homepage}}"
                        {% endif %}
                    ),
                    wcc.WebvizSettingsDrawer(
                        id="settings-drawer",
                        children=[],
                    ),
                    wcc.WebvizPluginsWrapper(
                        id="plugins-wrapper",
                        children=[],
                    )
                ]
            ),
        ]
    )

WEBVIZ_FACTORY_REGISTRY.cleanup_resources_after_plugin_init()

theme.adjust_csp({"script-src": app.csp_hashes()}, append=True)
Talisman(server, content_security_policy=theme.csp, feature_policy=theme.feature_policy, force_https=False, session_cookie_secure=False)

oauth2 = webviz_config.Oauth2(app.server) if use_oauth2 else None

@callback(
    Output("plugins-wrapper", "children"), 
    Output("settings-drawer", "children"), 
    Input("location", "pathname")
)
def update_page(pathname):
    ctx = callback_context
    if ctx.triggered:
        if pathname is not None:
            pathname = pathname.replace("/", "")
        else:
            pathname = ""
    if not pathname:
        pathname = next(iter(page_plugins)) 
    return page_plugins.get(pathname, ["Oooppss... Page not found."]), page_settings.get(pathname, [])

{{ "WEBVIZ_ASSETS.directly_host_assets(app)" if not portable else ""}}

if __name__ == "__main__":
    # This part is ignored when the webviz app is started
    # using Docker container and uwsgi (e.g. when hosted on Azure).
    #
    # It is used only when directly running this script with Python,
    # which will then initialize a localhost server.

    port = webviz_config.utils.get_available_port(preferred_port=5000)

    token = webviz_config.LocalhostToken(app.server, port, oauth2).one_time_token
    webviz_config.utils.LocalhostOpenBrowser(port, token)

    webviz_config.utils.silence_flask_startup()

    app.run_server(
        host="localhost",
        port=port,
        debug=False,
        use_reloader={{not portable}},
        dev_tools_prune_errors=False,
        {% if not portable -%}
        dev_tools_hot_reload=True,
        dev_tools_hot_reload_interval=1.0,
        dev_tools_silence_routes_logging=False,
        {% endif %}
        {% if debug %}
        dev_tools_ui=True,
        dev_tools_props_check=True,
        dev_tools_serve_dev_bundles=True,
        {% endif %}        
    )
else:
    # This will be applied if not running on localhost
    if use_oauth2:
        oauth2.set_oauth2_before_request_decorator()
