{% extends "page.html" %}

{% block stylesheet %}
{{super()}}
<style type="text/css">
/* disable initial hide */
div#header, div#site {
    display: block;
}
#output-box {
    display: block;
    width: 1150px;
    height: 300px;
    overflow-y: scroll;
    overflow-x: hidden;
    white-space: pre-wrap;
    text-align: left;
    border: 1px solid #ccc;
    background-color: #f7f7f7;
    padding: 10px;
    border-radius: 5px;
    margin-top: 15px;
}
#button-container {
    display: flex;
    justify-content: center;
    align-items: center;
    position: relative;
    margin-top: 25px;
}
.action-buttons {
    display: none;
    text-align: center;
    color: white;
    border: none;
    border-radius: 5px;
    padding: 10px 20px;
    font-size: 16px;
    cursor: pointer;
    transition: background-color 0.3s ease;
    margin: 20px;
}
#back-button, #modal-back-button { background-color: #fc6404; }
#modal-lab-button { background-color: #0454a4; }

#modal {
    display: none;
    position: fixed;
    z-index: 1;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    overflow: auto;
    background-color: rgba(0, 0, 0, 0.4);
}

#modal-title {
    margin-top: 2.5px;
}

#modal-content {
    background-color: #fefefe;
    margin: 15% auto;
    padding: 20px;
    border: 1px solid #888;
    width: 80%;
    max-width: 500px;
    border-radius: 5px;
    text-align: left;
}

#modal-button-container {
    display: flex;
    justify-content: flex-end;
}

#modal-button-container button {
    border: none;
    color: white;
    padding: 7.5px 15px;
    text-align: center;
    text-decoration: none;
    font-size: 16px;
    margin: 4px 2px;
    cursor: pointer;
    border-radius: 5px;
}

</style>
{% endblock %}

{% block params %}
{{super()}}
data-base-url="{{base_url | urlencode}}"
{% endblock %}

{% block site %}

<div class="container">
    <div id="modal">
        <div id="modal-content">
            <h2 id="modal-title" style="text-align: left;"></h2>
            <p id="modal-description">Restart the session to create a new environment, or go to JupyterLab to use the existing environment.</p>
            <div id="modal-button-container">
                <button id="modal-back-button">Restart session</button>
                <button id="modal-lab-button">JupyterLab</button>
            </div>
        </div>
    </div>
    <div class="row">
        <div class="swan-info">
            <div id="swan-loader">
                <div class="loader-circle">
                    <img src="{{hub_prefix}}static/swan/logos/{{swan_logo_filename}}">
                </div>
                <div class="loader-line-mask">
                    <div class="loader-line"></div>
                </div>
                <span class="text">Creating environment...</span>
            </div>
        </div>
        <br><br>
        <div id="output-box"></div>
        <div id="button-container">
            <button class="action-buttons" id="back-button">Restart session</button>
        </div>
    </div>
</div>

{% endblock %}

{% block script %}
    {{super()}}

<script type = "text/javascript">
    const redirect2Config = () => window.location = `/hub/home?changeconfig`;
    const redirect2Lab = (base_url, project_path) => window.location = `${base_url}lab${project_path}`;
    const get_jh_auth_header = () => {
        const cookie = document.cookie.match("\\b_xsrf=([^;]*)\\b");
        const xsrf = cookie ? cookie[1] : undefined;
        return xsrf ? {'X-XSRFToken': xsrf} : {}
    };

    var base_url = document.body.getAttribute('data-base-url');
    var project_path = '/';
    var env_name = `${base_url.split('/')[-1]}_env`;
    var has_failed = false, is_created = false;

    const urlParams = new URLSearchParams(window.location.search);
    var repository = urlParams.get('repo') || "";
    var builder = urlParams.get('builder') || "";
    var builder_version = urlParams.get('builder_version') || "";
    var file = `/${urlParams.get('file') || ""}`;
    var nxcals = urlParams.get('nxcals') || "";

    // Environment creation elements
    var outputBox = document.getElementById('output-box');
    var loader = document.getElementById('swan-loader');
    var back_button = document.getElementById('back-button');

    // Modal elements
    var modal = document.getElementById("modal");
    var modalTitle = document.getElementById("modal-title");
    var modalBackButton = document.getElementById("modal-back-button");
    var modalJupyter = document.getElementById("modal-lab-button");

    // Function to trigger a visual error in the loader
    const trigger_visual_error = (message) => {
        loader.getElementsByClassName('loader-line-mask')[0].style.display = 'none';
        loader.getElementsByClassName('text')[0].innerHTML = 'Error creating environment';
        back_button.onclick = () => redirect2Config();
        back_button.style.display = 'block';
        console.error(message);
    };

    // Function to process each chunk of data iteratively
    async function render_data_chunks(reader, decoder) {
        try {
            // Read chunks until the stream is done
            while (true) {
                // Wait for the next chunk of data
                const { done, value } = await reader.read();
                
                // Exit the loop if no more data is available
                if (done) {
                    loader.getElementsByClassName('loader-line-mask')[0].style.display = 'none';

                    // Output has errors -> change title and show button for going back to spawner
                    if (has_failed) {
                        trigger_visual_error("");
                    }

                    // Environment exists already -> ask user if they want to reconfigure it
                    else if (is_created) {
                        modalTitle.innerHTML = `This session already has an environment named ${env_name}`;
                        modalBackButton.onclick = () => redirect2Config();
                        modalJupyter.onclick = () => redirect2Lab(base_url, project_path);
                        modal.style.display = "block";
                    }

                    // Output is fine -> Redirect to JupyterLab
                    else {
                        redirect2Lab(base_url, project_path);
                    }
                    break; // Exit the loop after processing all data
                }

                // Decode the chunk into text and split by newlines
                // Remove the last element (empty string) for avoiding an extra line break
                const chunked_lines = decoder.decode(value, { stream: true }).split('\n').slice(0, -1);
                chunked_lines.forEach(message_line => {
                    if (message_line.startsWith('REPO_PATH')) {
                        const repo_path = message_line.split(':')[1];
                        if (repo_path && repo_path !== '/') {
                            project_path = `/tree${repo_path}${file}`;
                        }
                    } 
                    // Get the environment name from the output
                    else if (message_line.startsWith('ENV_NAME')) {
                        env_name = message_line.split(':')[1];
                    } 
                    // Environment already exists -> pops up a modal
                    else if (message_line.startsWith('ENVIRONMENT_ALREADY_EXISTS')) {
                        is_created = true;
                        env_name = message_line.split(':')[1];
                    } 
                    // Usual case -> update output box with the message received
                    else {
                        outputBox.innerHTML += message_line;
                        outputBox.scrollTop = outputBox.scrollHeight;
                        if (message_line.includes('ERROR')) {
                            has_failed = true;
                        }
                    }
                    outputBox.innerHTML += '<br>';
                });
            }
        } catch (error) {
            trigger_visual_error(`Error reading stream: ${error}`);
        }
    }

    fetch(`${base_url}api/customenvs?repo=${encodeURIComponent(repository)}&builder=${encodeURIComponent(builder)}&builder_version=${encodeURIComponent(builder_version)}&nxcals=${encodeURIComponent(nxcals)}`, {
        method: 'GET',
        headers: get_jh_auth_header(),
    })
    .then(response => {
        if (!response.ok) {
            trigger_visual_error(`Network response was not ok: ${response.statusText}`);
        } else {
            const reader = response.body.getReader();
            const decoder = new TextDecoder("utf-8");
            // Start reading the first chunk
            render_data_chunks(reader, decoder);
        }
    })
    .catch(error => {
        trigger_visual_error(`Error fetching stream: ${error}`);
    });

</script>
{% endblock %}
