<!doctype html>
<html>

<head>
    <title>{{title}}</title>
    <meta charset="utf-8">
    {{ pre_rendered_metas | safe }}
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
    <link rel="icon" type="image/png" sizes="any" href="{{root_path}}/static/assets/favicon.png">
    <link rel="icon" type="image/svg+xml" href="{{root_path}}/static/assets/favicon.svg">

    {% block header %}

    {{ pre_rendered_css | safe }}
    {% if vue3 == True %}
    <link href="{{cdn}}/@widgetti/solara-vuetify3-app@5.0.2/dist/main{{ipywidget_major_version}}.css" rel="stylesheet" class="solara-template-css"></link>
    {% else %}
    <link href="{{cdn}}/@widgetti/solara-vuetify-app@10.0.3/dist/main{{ipywidget_major_version}}.css" rel="stylesheet" class="solara-template-css"></link>
    {% endif %}


    {% if assets.fontawesome_enabled == True %}
    <link rel="stylesheet" href="{{cdn}}{{assets.fontawesome_path}}" type="text/css">
    {% endif %}
    {{ resources.include_css("/static/highlight.css") }}
    {{ resources.include_css("/static/highlight-dark.css") }}
    {{ resources.include_css("/static/assets/style.css") }}
    <style id="jupyter-theme-css" class="solara-template-css">
    </style>
    {{ resources.include_css("/static/assets/custom.css") }}

    <script id="jupyter-config-data" type="application/json">
    {
        "baseUrl": "{{jupyter_root_path}}/",
        "kernelId": "1234"
    }
    </script>
    <style class="solara-template-css">
        {% include "loader-"~theme.loader~".css" %}
    </style>
    <!-- Include Vuetify background colours so static html from SSG renders the right general colour theme
        before first render. We remove these after Vue takes over rendering to avoid collisions -->
    <style id="pre-render-theme">
    .theme--light .v-sheet {
        background-color: #fff;
        border-color: #fff;
        color: rgba(0,0,0,.87)
    }

    .theme--dark .v-sheet {
        background-color: #1e1e1e;
        border-color: #1e1e1e;
        color: #fff
    }
</style>
    {% endblock header %}
</head>
{% raw -%}
<script type="x-template" id="vue-app-template" style="display: none">
    <v-app :key="forceUpdateTrigger" :class="loadingPage ? 'solara-page-loading' : ''">
        <v-progress-linear :style="{visibility: (kernelBusyLong && isMounted) ? 'visible' : 'hidden'}" indeterminate
            absolute></v-progress-linear>
        <v-alert v-if="needsRefresh || cancelAutoRefresh" type="warning" border="left"
            style="position: absolute; right: 0px; z-index: 100; left: 0px;">
            App is disconnected, and may not function properly. Please refresh the page.
        </v-alert>
        {% endraw -%}
        {# {% include "transition-domino.html" %} #}
        {% include "loader-" ~ theme.loader ~ ".html" %}
        <v-overlay style="z-index: 100002;" :value="(connectionStatus != 'connected') & wasConnected">
            <v-progress-circular indeterminate size="128" style="text-align: center;">Server
                disconnected.</v-progress-circular>
        </v-overlay>

        <v-dialog v-model="needsRefresh" width="500">
            <v-card>
                <v-card-title class="text-h5 grey lighten-2">Please refresh the page</v-card-title>

                {% if production %}
                <v-card-text>
                    Could not restore session. Please refresh.
                </v-card-text>
                {% else %}
                <v-card-text>
                    {% raw -%}
                    Could not restore session. Will refresh in {{autoRefreshCount}} seconds.
                    {% endraw -%}
                </v-card-text>
                {% endif %}

                <v-divider></v-divider>

                <v-card-actions>
                    <v-spacer></v-spacer>
                    <v-btn color="secondary" text @click="reload()">
                        Refresh now
                    </v-btn>
                    <v-btn color="primary" text @click="setCancelAutoRefresh()">
                        Cancel
                    </v-btn>
                </v-card-actions>
            </v-card>
        </v-dialog>
        {% raw -%}

        <v-menu v-if="debug && solaraDebugMessages && solaraDebugMessages.length" offset-y top
            :close-on-content-click="false">
            <template v-slot:activator="{ on }">
                <v-btn text v-on="on" style="position: fixed; bottom: 8px; right: 8px">
                    <span style="color: red">{{ solaraDebugMessages.length }}</span>
                    <v-icon right large color="red">mdi-bug-outline</v-icon>
                </v-btn>
            </template>
            <v-sheet class="pa-2" style="overflow: auto; max-height: 80vh">
                <div style="display: flex" v-for="message in solaraDebugMessages" :key="message.cell" class="pa-2">
                    <div style="width: 50px">[{{ message.cell }}]</div>
                    <div v-if="message.traceback" class="jp-RenderedText jp-OutputArea-output"
                        data-mime-type="application/vnd.jupyter.stderr">
                        <pre v-html="message.traceback" class="pa-2"></pre>
                    </div>
                    <pre v-else><span :style="message.name === 'stderr' ? 'background-color: var(--jp-rendermime-error-background)' : ''"
                                class="pa-2"
                            >{{ message.text }}</span>
                    </pre>
                </div>
                <div class="d-flex justify-end">
                    <v-tooltip top>
                        <template v-slot:activator="{ on, attrs }">
                            <v-btn icon v-bind="attrs" v-on="on" @click="solaraDebugMessages = []">
                                <v-icon>mdi-trash-can-outline</v-icon>
                            </v-btn>
                        </template>
                        <span>Clear messages</span>
                    </v-tooltip>
                </div>
            </v-sheet>
        </v-menu>

        <!-- <v-menu v-if="debug && outputMessages && outputMessages.length" offset-y top
            :close-on-content-click="false">
            <template v-slot:activator="{ on }">
                <v-btn text v-on="on" style="position: fixed; top: 8px; right: 8px">
                    <span style="color: #333">{{ outputMessages.length }}</span>
                    <v-icon right large color="#333">mdi-information-outline</v-icon>
                </v-btn>
            </template>
            <v-sheet class="pa-2" style="overflow: auto; max-height: 80vh">
                <div style="display: flex" v-for="message in outputMessages" :key="message.cell" class="pa-2">
                    <div style="width: 50px">[{{ message.cell }}]</div>
                    <div v-if="message.traceback" class="jp-RenderedText jp-OutputArea-output"
                        data-mime-type="application/vnd.jupyter.stderr">
                        <pre v-html="message.traceback" class="pa-2"></pre>
                    </div>
                    <pre v-else><span :style="message.name === 'stderr' ? 'background-color: var(--jp-rendermime-error-background)' : ''"
                                class="pa-2"
                            >{{ message.text }}</span>
                    </pre>
                </div>
                <div class="d-flex justify-end">
                    <v-tooltip top>
                        <template v-slot:activator="{ on, attrs }">
                            <v-btn icon v-bind="attrs" v-on="on" @click="outputMessages = []">
                                <v-icon>mdi-trash-can-outline</v-icon>
                            </v-btn>
                        </template>
                        <span>Clear messages</span>
                    </v-tooltip>
                </div>
            </v-sheet>
        </v-menu> -->
    </v-app>
</script>
{% endraw -%}

<body data-base-url="{{root_path}}/jupyter/">
    {% if perform_check %}
    <iframe src="https://solara.dev/static/public/success.html?system=solara&check=html&version={{solara_version}}" style="display: none"></iframe>
    {% endif %}
    {% if theme.variant == "auto" %}
    {% endif %}
    {% if theme.variant == "light" %}
    <div id="app" class="v-application v-application--is-ltr theme--light" data-app="true">
    {% elif theme.variant == "dark" %}
    <div id="app" class="v-application v-application--is-ltr theme--dark" data-app="true">
    {% endif %}
        {{ pre_rendered_html|safe }}
        {# next div is used in ssg code to see if vue took over rendering #}
        <div id="pre-rendered-html-present" style="display: none"></div>
    </div>
    <script>
        var theme = {{ theme | tojson | safe }}
        function getThemeVariant() {
            if (localStorage.getItem(':solara:theme.variant')) {
                return JSON.parse(localStorage.getItem(':solara:theme.variant'))
            }
            return theme.variant;
        }
        if (localStorage.getItem(':solara:theme.variant')) {
            theme.variant = JSON.parse(localStorage.getItem(':solara:theme.variant'))
        }
        function prefersDarkScheme() {
            return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches
        }
        function inDarkMode() {
            if (getThemeVariant() == 'auto') {
                return prefersDarkScheme();
            }
            else {
                return getThemeVariant() == 'dark';
            }
        }
        // Init theme
        let appContainer = document.getElementById('app');
        const searchParams = new URLSearchParams(window.location.search);
        if(searchParams.has('modelid')) {
            // indicates that we are not mounting the application, but a specific
            // widget (for instance using ipypopout)
            document.body.classList.add('jupyter-widgets-popout-container');
        }
        if (inDarkMode()) {
            appContainer.classList.remove('theme--light');
            appContainer.classList.add('theme--dark');
        } else {
            appContainer.classList.remove('theme--dark');
            appContainer.classList.add('theme--light');
        }
    </script>
    {% block after_pre_rendered_html %}{% endblock %}
    {% if vue3 == True %}
        <link href="{{cdn}}/@widgetti/solara-vuetify3-app@5.0.2/dist/fonts.css" rel="stylesheet"></link>
        {% if production %}
        <script src="{{cdn}}/@widgetti/solara-vuetify3-app@5.0.2/dist/solara-vuetify-app{{ipywidget_major_version}}.min.js"></script>
        {% else %}
        <script src="{{cdn}}/@widgetti/solara-vuetify3-app@5.0.2/dist/solara-vuetify-app{{ipywidget_major_version}}.js"></script>
        {% endif %}
    {% else %}
        <link href="{{cdn}}/@widgetti/solara-vuetify-app@10.0.3/dist/fonts.css" rel="stylesheet" fetchpriority="low"></link>
        {% if production %}
        <script src="{{cdn}}/@widgetti/solara-vuetify-app@10.0.3/dist/solara-vuetify-app{{ipywidget_major_version}}.min.js"></script>
        {% else %}
        <script src="{{cdn}}/@widgetti/solara-vuetify-app@10.0.3/dist/solara-vuetify-app{{ipywidget_major_version}}.js"></script>
        {% endif %}
    {% endif %}
    <script>
        solara.rootPath = {{ root_path | tojson | safe}};
        solara.jupyterRootPath = {{ jupyter_root_path | tojson | safe}};
        solara.cdn = {{ cdn | tojson | safe }};
        // the vue templates expect it to not have a trailing slash
        solara.cdn = solara.cdn.replace(/\/$/, '');
        // keep this for backwards compatibility
        window.solara_cdn = solara.cdn;
        console.log("solara config", {rootPath: solara.rootPath, jupyterRootPath: solara.jupyterRootPath, cdn: solara.cdn});

        async function changeThemeCSS(theme) {
            let css = await fetch(`${solara.rootPath}/static/assets/theme-${theme}.css`).then(r => r.text());
            document.getElementById('jupyter-theme-css').innerHTML = css;
        }
        changeThemeCSS(inDarkMode() ? 'dark' : 'light');
    </script>

    {{ resources.include_js("/static/assets/custom.js") }}
    {{ resources.include_js("/static/assets/theme.js") }}

    <script src="{{cdn}}/requirejs@2.3.6/require.js" crossorigin="anonymous">
    </script>
    {{ resources.include_js("/static/main-vuetify.js") }}
    {{ resources.include_js("/static/ansi.js") }}

    <script>
        solara.production = {{ production | tojson | safe }};
        const themeVariants = ['light', 'dark', 'auto']
        solara.preRendered = {{ pre_rendered_html | safe | length | tojson }} > 0
        if(solara.preRendered) {
            document.body.classList.add('solara-ssg', 'solara-pre-rendered');
        } else {
            document.body.classList.add('solara-no-ssg');
        }

    </script>

    <script>
        window.solara.browser_platform = false;
        {% if platform == "emscripten" %}
        window.solara.browser_platform = true;
        {% endif %}
        var debug = true;

        var appComponent = {
            // if we do prerendering, keep it unmounted, and mount
            // when loading becomes false
            el: solara.preRendered ? null : '#app' ,
            template: '#vue-app-template',
            created() {
                const original_$forceUpdate = this.$forceUpdate.bind(this);
                this.$forceUpdate = (() => {
                    this.forceUpdateTrigger += 1;
                    original_$forceUpdate();
                });
                // in case we are showing a popop (e.g. using ipypopout), hide the banner
                if(searchParams.has('modelid')) {
                    this.showBanner = false;
                }
            },
            mounted() {
                document.querySelector('#app').removeAttribute("style");
                // listen to change in preferred color scheme (e.g if choosing dark in OSX)
                window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
                    this.$vuetify.theme.dark = inDarkMode();
                });
                document.getElementById('pre-render-theme').remove();
            },
            methods: {
                stateReset() {
                    console.log('reset')
                    msg = { "type": "state_reset", "reason": "user command" }
                    wsWatchdog.send(JSON.stringify(msg))
                },
                setCancelAutoRefresh() {
                    this.needsRefresh = false;
                    this.cancelAutoRefresh = true;
                },
                reload() {
                    location.reload();
                },
            },
            watch: {
                kernelBusy: function (value) {
                    if(this._lastBusyTimer) {
                        clearTimeout(this._lastBusyTimer)
                    }
                    if(value) {
                        this._lastBusyTimer = setTimeout(() => {
                            this.kernelBusyLong = value;
                        }, 300);
                    } else {
                        this.kernelBusyLong = value;
                    }
                },
                loading: function (value) {
                    // if preRendered, the app is not mounted yet
                    // so we mount it when loading becomes false
                    if (solara.preRendered && !this.mounted) {
                        function waitForAnimation(element) {
                            return new Promise((resolve) => {
                                element.addEventListener('animationend', resolve, { once: true });
                            });
                        }

                        function waitForAllAnimations(elements) {
                            const animationPromises = Array.from(elements).map(element => waitForAnimation(element));
                            return Promise.all(animationPromises);
                        }

                        (async () => {
                            await waitForAllAnimations(document.querySelectorAll('.solara-ssg-wait-for-animation'));
                            console.log("animation finished");
                            document.body.classList.remove('solara-pre-rendered');
                            document.body.classList.add('solara-pre-rendered-finished');
                            this.isMounted = true;
                            this.$mount("#app")
                        })();
                    } else {
                        this.isMounted = true;
                    }
                },
                needsRefresh: function (value) {
                    if (this.needsRefresh && !this.cancelAutoRefresh && !solara.production) {
                        console.log('value for needRefresh', value);
                        setTimeout(() => {
                            console.log('this.autoRefreshCount', this.autoRefreshCount)
                            this.autoRefreshCount = this.autoRefreshCount - 1;
                        }, 1000);
                    }
                },
                autoRefreshCount: function (value) {
                    console.log('value for autoRefreshCount', value);
                    if (value == 0) {
                        if (!this.cancelAutoRefresh)
                            this.reload();
                    } else if (value > 0) {
                        setTimeout(() => {
                            console.log('this.autoRefreshCount!', this.autoRefreshCount)
                            this.autoRefreshCount = this.autoRefreshCount - 1;
                        }, 1000);
                    }
                },
                '$vuetify.theme.dark': function (value) {
                    if ( value ) {
                        changeThemeCSS('dark');
                        appContainer.classList.remove('theme--light');
                        appContainer.classList.add('theme--dark');
                    } else {
                        changeThemeCSS('light');
                        appContainer.classList.remove('theme--dark');
                        appContainer.classList.add('theme--light');
                    }
                }
            },
            data() {
                return {
                    forceUpdateTrigger: 0,
                    loading_text: "Loading resources",
                    loadingPercentage: -1,
                    loading: true,
                    title: "No title",
                    solaraDebugMessages: [],
                    outputMessages: [],
                    theme: theme,
                    debug: debug,
                    connectionStatus: null,
                    wasConnected: false,
                    needsRefresh: false,
                    cancelAutoRefresh: false,
                    autoRefreshCount: 3,
                    kernelBusy: false,
                    isMounted: false,
                    loadingPage: false,
                    _lastBusyTimer: null,
                    kernelBusyLong: false,
                    showBanner: theme.show_banner,
                    // outputMessages: [{ name: 'stderr', text: 'lala' }],
                }
            }
        };
        const vue3 = Vue.version.startsWith('3');
        if(vue3) {
            var app = Vue.createApp(appComponent).use(vuetifyPlugin)
                .component("jupyter-widget-mount-point", jupyterWidgetMountPoint)
                .mount('#app');

        } else {
            Vue.component('jupyter-widget-mount-point', jupyterWidgetMountPoint);
            Vue.use(Vuetify);
            var app = new Vue({
                vuetify: new Vuetify({
                    theme: {
                        dark: inDarkMode(),
                        themes: vuetifyThemes,
                    },
                }),
                ...appComponent,
            });
        }
        // Loading classic notebook extensions.
        {% if 'jupyter-vuetify/extension' in resources.nbextensions -%}
        window.enable_nbextensions = true;
        {% endif -%}
        nbextensionHashes = {{ resources.nbextensions_hashes | tojson | safe }};
        requirejs.config({
            baseUrl: '{{jupyter_root_path}}',
            waitSeconds: 3000,
            map: {
                '*': {
                        {% if 'jupyter-vue/extension' in resources.nbextensions -%}
        'jupyter-vue': 'nbextensions/jupyter-vue/nodeps',
            {% endif -%}
        {% if 'jupyter-vuetify/extension' in resources.nbextensions -%}
        'jupyter-vuetify': 'nbextensions/jupyter-vuetify/nodeps',
            {% endif -%}
                    },
                },
                // Add cache busting to the urlArgs to ensure latest versions of nbextensions are loaded
                urlArgs: function (id, url) {
                    const extensionName = id.replace("/static/nbextensions/", "").replace(".js", "");
                    if (nbextensionHashes[extensionName] !== undefined) {
                        // Check if the url already has a query string, if so, append the hash as an additional parameter
                        return (url.indexOf('?') === -1 ? '?' : '&') + nbextensionHashes[extensionName];
                    } else {
                        return '';
                    }
                },
            });
        requirejs([
            {% for ext in resources.nbextensions if ext != 'jupyter-vuetify/extension' and ext != 'jupyter-vue/extension' -%}
        "{{jupyter_root_path}}/nbextensions/{{ ext }}.js",
            {% endfor %}
        ]);
        (async function () {
            await Promise.all([
                solaraInit('solara-main')
            ]);
        })();

    </script>

</html>
