<!-- 
    This HTML template file is used for visualizing the InstructScore data.
    It extends the "base.html" template and contains blocks for title and content.
    The content includes a loop to display predictions and references, as well as statistics and pagination controls.
    The predictions are displayed with error information, and the references are displayed separately.
    The statistics include the total number of errors, average number of errors per prediction, and most frequent types of errors.
    The pagination controls allow the user to navigate between pages of data.
    The hidden form and JavaScript functions are used to update the file value and submit the form when navigating between pages.
-->
{% extends "base.html" %}

{% block title %}
InstructScore Visualizer
{% endblock %}

{% block content %}



<body>

<style>
    .search-container, .conjunction-container {
        display: flex;
        justify-content: center;
        margin-bottom: 20px;
    }

    .search-container select,
    .search-container input,
    .conjunction-container select,
    .conjunction-container input {
        padding: 10px;
        border: 1px solid #ccc;
        border-radius: 4px 0 0 4px;
        outline: none;
        transition: border-color 0.3s;
    }

    .search-container select {
        border-radius: 4px 0 0 4px;
        border-right: none;
    }

    .search-container input {
        flex: 1;
        max-width: 500px;
        border-radius: 0;
        border-left: none;
    }

    .search-container input:focus {
        border-color: #3f51b5;
    }


    .conjunction-container select,
    .conjunction-container input {
        padding: 10px;
        border: 1px solid #ccc;
        border-radius: 4px;
        outline: none;
        transition: border-color 0.3s;
    }

    .conjunction-container select {
        margin-right: 10px;
    }

    .conjunction-container input:focus {
        border-color: #3f51b5;
    }


    .button-container {
        display: flex;
        flex-direction: column;
        position: absolute;
        left: 0;
    }

    .move-up-button {
        margin-bottom: -45%;
        background: none;
        border: none;
        cursor: pointer;
        font-size: 25px;
    }

    .move-down-button {
        margin-top: -45%;
        background: none;
        border: none;
        cursor: pointer;
        font-size: 25px;
    }

    .prediction {
    position: relative;
    padding-left: 20px; /* Adjust this value if needed to prevent overlap with buttons */
    }

    .score-container {
        display: flex;
        flex-direction: column;
        justify-content: flex-end;
        text-align: right;
        margin-bottom: 10px;
        font-size: 15px;
    }

    .filename {
        font-size: 20px;
        font-weight: bold;
        color: black;
        margin: 0px;
    }

    .score {
        font-size: 15px;
        font-weight: italic;
        color: black;
        margin: 0px;
    }

</style>

<div class="content-holder">
    <div class="container" style="margin-top: 5vh">
            <form method="POST" action="{{ url_for('dashboard')}}" class="input-form" id="goToDashboard">
                <input type="hidden" name="current_page" id="search_page" value="{{ current_page }}">
                {% for file in files%}
                    <input type="hidden" name="files" id="files_search" value={{ file }}>
                {% endfor %}
                <button type="submit" class="submit-button">Compare System-Level Stats</button>
            </form>

            <form method="POST" action="{{ url_for('visualize_instruct') }}" class="input-form" id="search-form">
            {% for i in range(search_options|length) %}
                {% if loop.first %}
                    <div class = "search-container" id="clearSearchContainer">
                        <button type="button" class="remove-button" onclick="clearSearchCacheAndReload()">Clear Search</button>
                    </div>
                {% endif%}
                <div class="search-container" id="form-row-{{ i+1 }}">
                    <select name="search_options[]" onchange="handleOptionChange(this)">
                        <option value="" disabled selected>Search Field</option>
                        <option value="src.source_text" {% if "src.source_text" == search_options[i] %}selected{% endif %}>Source Text</option>
                        <option value="preds.source_text" {% if "preds.source_text" == search_options[i] %}selected{% endif %}>Prediction Text</option>
                        <option value="refs.source_text" {% if "refs.source_text" == search_options[i] %}selected{% endif %}>Reference Text</option>
                        <option value="preds_text.error_type" {% if "preds_text.error_type" == search_options[i] %}selected{% endif %}>Error Type</option>
                        <option value="preds_text.error_scale" {% if "preds_text.error_scale" == search_options[i] %}selected{% endif %}>Error Scale</option>
                        <option value="preds_text.error_explanation" {% if "preds_text.error_explanation" == search_options[i] %}selected{% endif %}>Error Explanation</option>
                        <option value="runs.source_language" {% if "runs.source_language" == search_options[i] %}selected{% endif %}>Source Language</option>
                        <option value="refs.lang" {% if "refs.lang" == search_options[i] %}selected{% endif %}>Target Language</option>
                    </select>
                    <input type="text" name="search_texts[]" placeholder="Search..." value="{{ search_texts[i] }}">
                    {% if i > 0%}
                        <button type="button" class="remove-button" onclick="removeRow(this)">Remove</button>
                    {% else %}
                        <button type="submit" class="submit-button">Search</button>
                    {% endif %}
                </div>
                {% if i < conjunctions|length %}
                    <div class = 'conjunction-container' id="conjunction-container-{{ i+1 }}">
                        <select name="conjunctions[]" class="conjunction" onchange="addNewSearchRow(this)">
                            <option value="" disabled>Add another search term:</option>
                            <option value="AND" {% if conjunctions[i] == 'AND' %}selected{% endif %}>AND</option>
                            <option value="OR" {% if conjunctions[i] == 'OR' %}selected{% endif %}>OR</option>
                            <option value="NOT" {% if conjunctions[i] == 'NOT' %}selected{% endif %}>AND NOT</option>
                        </select>
                    </div>
                {% endif %}
            {% endfor %}
            {% if search_options|length == 0 %}
                <div class="search-container" id="form-row-1">
                    <select name="search_options[]" onchange="handleOptionChange(this)">
                        <option value="" disabled selected>Search Field</option>
                        <option value="src.source_text">Source Text</option>
                        <option value="preds.source_text">Prediction Text</option>
                        <option value="refs.source_text">Reference Text</option>
                        <option value="preds_text.error_type">Error Type</option>
                        <option value="preds_text.error_scale">Error Scale</option>
                        <option value="preds_text.error_explanation">Error Explanation</option>
                        <option value="runs.source_language">Source Language</option>
                        <option value="refs.lang">Target Language</option>
                    </select>
                    <input type="text" name="search_texts[]" placeholder="Search...">
                    <button type="submit" class="submit-button">Search</button>
                </div>
            {% endif %}
            <input type="hidden" name="current_page" id="search_page" value="{{ current_page }}">
            {% for file in files%}
                <input type="hidden" name="files" id="files_search" value={{ file }}>
            {% endfor %}
        </form>
        
        
    </div>

    {% for key, evaluation in input_data.items() %}
        {% set outerloop_index = loop.index%}
        {% set is_not_first = False %}
        <div class="container">
            {% if evaluation.source is not none %}
                <div class="container-with-shadow">
                    <h1 class="pred-ref">Source:</h1>
                    <span class="description">{{ evaluation.source }}</span>
                </div>
            {% endif %}
            <div>
                {% for file, data in evaluation.runs.items() %}
                    <div class="container-with-shadow prediction" id="prediction-{{ outerloop_index }}-{{ loop.index }}">
                        {% if not loop.first %}
                            <div class="button-container">
                                <button type="button" class="move-up-button" id="moveUp-{{ outerloop_index }}-{{ loop.index }}" onclick="moveUp('prediction-{{ outerloop_index }}-{{ loop.index }}')">⬆</button>
                            </div>
                        {% endif %}
                        <div class = "score-container">
                            {% if data.se_score %}
                                <span class="score">InstructScore: {{ data.se_score }}</span>
                            {% endif %}
                            {% if data.comet_score %}
                                <span class="score">COMET: {{ data.comet_score }}</span>
                            {% endif %}
                        </div>
                        <h1 class="filename">{{ file }}</h1>
                        <h1 class="pred-ref">Prediction:</h1> <span style="display: hidden;" id="pred-id-{{ outerloop_index }}-{{ loop.index }}">{{data.pred_id}}</span>
                        {% set is_not_first = True %}
                        {% for key, value in data.prediction.items() %}
                            {% if value == "None" %}
                                <span class="description">{{ key }}</span>
                            {% elif value is mapping %}
                                {% if value.color == "orange" %}
                                    <span class="orange-text">{{ key }}</span>
                                {% elif value.color == "blue" %}
                                    <span class="blue-text">{{ key }}</span>
                                {% elif value.color == "red" %}
                                    <span class="red-text">{{ key }}</span>
                                {% else %}
                                    <span class="description">{{ key }}</span>
                                {% endif %}
                                <span class="tooltip">
                                    Error Type: {{ value.error_type }}<br>
                                    Major/minor: {{ value.error_scale }}<br>
                                    Error explanation: {{ value.error_explanation }}
                                </span>
                            {% else %}
                                {{ value }}
                            {% endif %}
                            {% if not loop.last %} {% endif %}
                        {% endfor %}

                        <div class="button-container">
                            {% if not loop.last %}
                                <button type="button" class="move-down-button" id="moveDown-{{ outerloop_index }}-{{ loop.index }}" onclick="moveDown('prediction-{{ outerloop_index }}-{{ loop.index }}')">⬇</button>
                            {% endif %}
                        </div>
                    </div>
                {% endfor %}
            </div>

            {% if evaluation.reference is not none %}
                <div class="container-with-shadow">
                    <h1 class="pred-ref">Reference:</h1>
                    <span class="description">{{ evaluation.reference }}</span>
                </div>
            {% endif %}
        </div>
    {% endfor %}


    

    <!-- Pagination controls -->
        <!-- Pagination controls -->
    <div class = "pagination">
            {% if current_page > 1 %}
                <div>
                    <form id="hiddenForm_previous" method="POST" action="{{ url_for('visualize_instruct') }}">
                        {% for file in files%}
                            <input type="hidden" name="files" id="files_previous" value={{ file }}>
                        {% endfor %}
                        <input type="hidden" name="current_page" id="previous_page" value={{ current_page-1}}>
                        <button type="submit" class="pagination-button">Previous</button>
                    </form>
                </div>
            {% endif %}
        
        <div class="pagination-text">
            Page {{ current_page }} of {{ total_pages }}
        </div>
        
        
            {% if current_page < total_pages %}
                <!-- Next button with onclick event to update the form -->
                <div>
                    <form id="hiddenForm_next" method="POST" action="{{ url_for('visualize_instruct') }}">
                        {% for file in files%}
                            <input type="hidden" name="files" id="files_next" value={{ file }}>
                        {% endfor %}
                        <input type="hidden" name="current_page" id="next_page" value={{ current_page+1}}>
                        <button type="submit" class="pagination-button">Next</button>
                    </form>
                </div>
            {% endif %}
        


    </div>
</div>

 

    

    
</body>


   <script>
         const searchOptionsAll = [
            { value: 'src.source_text', text: 'Source Text' },
            { value: 'preds.source_text', text: 'Prediction Text' },
            { value: 'refs.source_text', text: 'Reference Text' },
            { value: 'preds_text.error_type', text: 'Error Type' },
            { value: 'preds_text.error_scale', text: 'Error Scale' },
            { value: 'preds_text.error_explanation', text: 'Error Explanation' },
            { value: 'runs.source_language', text: 'Source Language' },
            { value: 'refs.lang', text: 'Target Language' }
        ];

        function handleOptionChange(selectElement) {
            const formRowId = selectElement.parentElement.id;
            let conjunctionContainer = document.getElementById(`conjunction-container-${parseInt(selectElement.parentElement.id.split('-')[2])}`);
            const form = document.getElementById('search-form');

            if (!conjunctionContainer) {
                // Add conjunction dropdown
                const conjunctionSelect = document.createElement('select');
                conjunctionSelect.name = 'conjunctions[]';
                conjunctionSelect.className = 'conjunction';
                conjunctionSelect.innerHTML = `
                    <option value="" disabled selected>Add another search term:</option>
                    <option value="AND">AND</option>
                    <option value="OR">OR</option>
                    <option value="NOT">AND NOT</option>
                `;
                conjunctionSelect.onchange = function() {
                        if (!document.getElementById(`form-row-${parseInt(selectElement.parentElement.id.split('-')[2]) + 1}`)) {
                            addNewSearchRow(selectElement, conjunctionSelect);
                            
                        }
                };

                conjunctionContainer = document.createElement('div');
                conjunctionContainer.className = 'conjunction-container';
                conjunctionContainer.id = `conjunction-container-${parseInt(selectElement.parentElement.id.split('-')[2])}`;
                conjunctionContainer.appendChild(conjunctionSelect);
                selectElement.parentElement.parentElement.appendChild(conjunctionContainer);
            }
        }

        function addNewSearchRow(previousSelect, conjunctionSelect) {
            console.log("in addNewSearchRow");
            console.log("previousSelect", previousSelect);
            console.log("conjunctionSelect", conjunctionSelect);
            if (!document.getElementById(`form-row-${parseInt(previousSelect.parentElement.id.split('-')[2]) + 1}`)) {
                _addNewSearchRow(previousSelect, conjunctionSelect);             
            }
        };

        function _addNewSearchRow(previousSelect, conjunctionSelect) {
            const form = document.getElementById('search-form');
            const selectedOptions = [...form.querySelectorAll('.search-options')].map(select => select.value);

            let remainingOptions = searchOptionsAll.filter(option => !selectedOptions.includes(option.value));

            if (remainingOptions.length === 0) return;

            // Create new form row
            const newRow = document.createElement('div');
            newRow.className = 'search-container added-row';
            newRow.id = `form-row-${form.querySelectorAll('.search-container').length + 1}`;

            // Create new search option dropdown
            const newSelect = document.createElement('select');
            newSelect.name = 'search_options[]';
            newSelect.innerHTML = `
                <option value="" disabled selected>Search Field</option>`;
            newSelect.onchange = function() {
                handleOptionChange(newSelect);
            };

            remainingOptions.forEach(option => {
                const optionElement = document.createElement('option');
                optionElement.value = option.value;
                optionElement.text = option.text;
                newSelect.appendChild(optionElement);
            });

            // Create new search text input
            const newInput = document.createElement('input');
            newInput.type = 'text';
            newInput.name = 'search_texts[]';
            newInput.placeholder = 'Search...';

            // Create remove button
            const removeButton = document.createElement('button');
            removeButton.type = 'button';
            removeButton.innerText = 'Remove';
            removeButton.className = 'remove-button';
            removeButton.onclick = function() {
                removeRow(removeButton);
            };

            newRow.appendChild(newSelect);
            newRow.appendChild(newInput);
            newRow.appendChild(removeButton);

            form.appendChild(newRow);
        }


    function removeRow(button) {
        console.log(button);
        let conjunctionContainer = button.parentElement.nextElementSibling;

        if (conjunctionContainer) {
            conjunctionContainer.remove();
        }

        button.parentElement.remove();
    }

    document.addEventListener('DOMContentLoaded', function () {
        const searchOptions = {{ search_options|tojson }};
        const searchTexts = {{ search_texts|tojson }};
        const conjunctions = {{ conjunctions|tojson }};

        if (searchOptions.length > 0) {
            const form = document.getElementById('search-form');
            for (let i = 1; i < searchOptions.length; i++) {
                addNewSearchRow(null, form.querySelector('.conjunction'));
            }
        }
    });

    function moveUp(predictionId) {
        const currentElement = document.getElementById(predictionId);
        const previousElement = currentElement.previousElementSibling;

        if (previousElement && previousElement.classList.contains('prediction')) {
            currentElement.parentNode.insertBefore(currentElement, previousElement);
        }

        recalibrateButtons(predictionId);

        log_ranking(currentElement, previousElement);
    }

    function moveDown(predictionId) {
        const currentElement = document.getElementById(predictionId);
        const nextElement = currentElement.nextElementSibling;

        if (nextElement && nextElement.classList.contains('prediction')) {
            currentElement.parentNode.insertBefore(nextElement, currentElement);
        }

        recalibrateButtons(predictionId);
        log_ranking(nextElement, currentElement);
    }

    function recalibrateButtons(predictionId) {
        const currentElement = document.getElementById(predictionId);
        const predictionIdParts = predictionId.split('-');
        const number1 = predictionIdParts[1];
        const number2 = predictionIdParts[2];
        const extractedString = `-${number1}-${number2}`;
        const downButtonId = `moveDown${extractedString}`;
        const upButtonId = `moveUp${extractedString}`;

        // Check if it is now the bottom element
        const newNextElementSibling = currentElement.nextElementSibling;
        if (!newNextElementSibling || !newNextElementSibling.classList.contains('prediction')) {
            const downButton = document.getElementById(`moveDown${extractedString}`);
            if (downButton) {
                downButton.remove();
            }
        }
        else {
            // Check if the current element has a down button, if not, add one
            let downButton = document.getElementById(downButtonId);
            if (!downButton) {
                createButtonWithContainer(downButtonId, currentElement, "down");
            }

            const nextElementId = newNextElementSibling.id;
            const nextElementExtractedString = nextElementId.split('-');
            // Check if the next element has a up button, if not, add one
            const nextElementUpButtonId = `moveUp-${nextElementExtractedString[1]}-${nextElementExtractedString[2]}`;
            let nextUpButton = document.getElementById(nextElementUpButtonId);
            if (!nextUpButton) {
                createButtonWithContainer(nextElementUpButtonId, newNextElementSibling, "up");
            }


            // Check if the next element is the bottom element, then remove the down button
            const nextElement = newNextElementSibling.nextElementSibling;
            if (!nextElement || !nextElement.classList.contains('prediction')) {
                const nextElementDownButtonId = `moveDown-${nextElementExtractedString[1]}-${nextElementExtractedString[2]}`;
                const nextDownButton = document.getElementById(nextElementDownButtonId);
                if (nextDownButton) {
                    button_container = nextDownButton.parentElement;
                    nextDownButton.remove();
                    button_container.remove();
                }
            }
        }

        // Check if it is now the top element
        const newPreviousElement = currentElement.previousElementSibling;
        if (!newPreviousElement || !newPreviousElement.classList.contains('prediction')) {
            const upButton = document.getElementById(`moveUp${extractedString}`);
            if (upButton) {
                upButton.remove();
            }
        }
        else {
            // Check if the current element has a up button, if not, add one
            let upButton = document.getElementById(upButtonId);
            if (!upButton) {
                createButtonWithContainer(upButtonId, currentElement, "up");

            }

            const previousElementId = newPreviousElement.id;
            const previousElementExtractedString = previousElementId.split('-');

            // Check if the previous element has a down button, if not, add one
            const previousElementDownButtonId = `moveDown-${previousElementExtractedString[1]}-${previousElementExtractedString[2]}`;
            let previousDownButton = document.getElementById(previousElementDownButtonId);
            if (!previousDownButton) {
                createButtonWithContainer(previousElementDownButtonId, newPreviousElement, "down");
            }

            // Check if the previous element is the first element, then remove the up button
            const previousElement = newPreviousElement.previousElementSibling;
            if (!previousElement || !previousElement.classList.contains('prediction')) {
                
                const previousElementUpButtonId = `moveUp-${previousElementExtractedString[1]}-${previousElementExtractedString[2]}`;
                const previousUpButton = document.getElementById(previousElementUpButtonId);
                if (previousUpButton) {
                    button_container = previousUpButton.parentElement;
                    previousUpButton.remove();
                    button_container.remove();
                }
            }
        }
    }

    function createButtonWithContainer(buttonId, currentElement, button_type) {

        const button = document.createElement('button');

        if (button_type == "up") {
            button.className = 'move-up-button';
            button.innerText = '⬆';
            button.onclick = function() {
                moveUp(currentElement.id);
            };
        }

        else {
            button.className = 'move-down-button';
            button.innerText = '⬇';
            button.onclick = function() {
                moveDown(currentElement.id);
            };
        }

        button.type = 'button';
        button.id = buttonId;

        const buttonContainer = document.createElement('div');
        buttonContainer.className = 'button-container';
        buttonContainer.appendChild(button);
        
        if (button_type == 'up') {
            currentElement.prepend(buttonContainer);
        }

        else {
            currentElement.appendChild(buttonContainer);
        }

    }

    function log_ranking(higherElement, lowerElement) {
        higherIndices = higherElement.id.split('-');
        lowerIndices = lowerElement.id.split('-');

        higherPredId = document.getElementById(`pred-id-${higherIndices[1]}-${higherIndices[2]}`).innerText;
        lowerPredId = document.getElementById(`pred-id-${lowerIndices[1]}-${lowerIndices[2]}`).innerText;

        fetch('/log', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                higherPredId: higherPredId,
                lowerPredId: lowerPredId
            })
        })
            .then(response => {
                console.log("Success!: ", response);
            })
            .catch(error => {
                console.log("Failure :( : ", response);
            });
    }

    function clearSearchCacheAndReload() {
        console.log("clearing search")
        document.querySelectorAll('select[name="search_options[]"]').forEach(select => select.selectedIndex = 0);
        document.querySelectorAll('input[name="search_texts[]"]').forEach(input => input.value = '');
        document.querySelectorAll('select[name="conjunctions[]"]').forEach(select => select.selectedIndex = 0);
        document.getElementById('search_page').value = 1;
        fetch(
            '/clear_search_cache',
            {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify({})
            }
        ).then(() => {
            document.getElementById('search-form').submit();
        });
        // Optionally, reset the form to its initial state

    }

    </script>

{% endblock %}
