document.addEventListener('keydown', function (e) {
    // Mac = Option, Windows/Linux = Alt
    const isOptionOrAlt = e.altKey || e.metaKey; 
    
    if (isOptionOrAlt && e.shiftKey && e.key.toLowerCase() === 'f') {
        toggleFullscreen();
    }

    if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {
        e.preventDefault();
    }
});

function toggleFullscreen() {
    // If not in fullscreen → enter fullscreen
    if (!document.fullscreenElement) {
        document.documentElement.requestFullscreen()
            .catch(err => console.error("Fullscreen error:", err));
    } 
    // If already fullscreen → exit fullscreen
    else {
        document.exitFullscreen();
    }
}

let messagePosArray = [];
const csrf_token = window.CSDR_TOKEN;

const text = document.getElementById('wsInfo');
const rect = document.getElementById('wsInfoRectangle');

let ws;
let firstConnect = true;
let wsOpen = false;
const RETRY_DELAY = 2000; // ms

const WSaccesstype = "kampfrichter";
const WSaccess = window.FREIGABE;
const WSaccessPermission = "W";

const urlAjaxNewWSToken = '/intern/scripts/ajax-create-ws-token.php';

async function fetchNewWSToken(accesstype, access, accessPermission) {
    try {
        const response = await fetch(urlAjaxNewWSToken, {
            method: "POST",
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
            },
            body: new URLSearchParams({ 
                csrf_token,
                accesstype, 
                access, 
                accessPermission 
            })
        });

        if (response.status === 403) {
            console.warn("Please Re-Autenithicate. Reloading page...");
            location.reload(); 
            return null;
        }

        if (!response.ok) return null;

        const data = await response.json();
        return data.success ? data.token : null;
    } catch (error) {
        console.error("Token fetch failed:", error);
        return null;
    }
}

async function startWebSocket() {
    console.log("Attempting WebSocket connection...");

    let token;
    if (firstConnect) {
        token = window.WS_ACCESS_TOKEN;
    } else {
        token = await fetchNewWSToken(WSaccesstype, WSaccess, WSaccessPermission);
    }

    if (!token) {
        console.error("No valid token available. Retrying...");
        scheduleRetry();
        return;
    }

    try {
        ws = new WebSocket(`wss://${window.location.hostname}/ws/?access=token&token=${token}`);
    } catch (err) {
        console.error("Malformed WebSocket URL", err);
        scheduleRetry();
        return;
    }

    ws.onopen = () => {
        console.log("WebSocket connected!");
        if (!firstConnect) {
            displayMsg(1, "Live Syncronisation wieder verfügbar");
        }
        firstConnect = true;
        wsOpen = true;

        rect.innerHTML =
            '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="10" fill="#28a745"></circle><path d="M7 12l3 3 7-7" stroke="white" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"></path></svg>';

        requestAnimationFrame(() => {
            text.style.opacity = 1;
        });
    };

    ws.onerror = (event) => {
        console.error("WebSocket error observed." + JSON.stringify(event));
    };

    ws.onclose = (event) => {

        if (firstConnect) {
            displayMsg(0, "Live Syncronisation verloren");
            console.log(event);
        }
        firstConnect = false;
        wsOpen = false;
        rect.innerHTML =
            '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="10" fill="#dc3545"/><path d="M8 8l8 8M16 8l-8 8" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>';

        requestAnimationFrame(() => {
            text.style.opacity = 1;
        });

        scheduleRetry();
    };
}

function scheduleRetry() {
    console.log(`Retrying in ${RETRY_DELAY}ms...`);
    setTimeout(startWebSocket, RETRY_DELAY);
}

// Start the initial connection attempt safely
startWebSocket();

function updateRunButtons(targetCount, personId, $container) {

    if (targetCount === 0) { return; }

    const geraetId = $container.find('.submit-display-result').first().data('geraet-id') || "";

    const currentCount = $container.find('.submit-display-result').length;

    $container.find('.submit-display-result').removeClass('hidden');

    if (targetCount > currentCount) {
        for (let i = currentCount + 1; i <= targetCount; i++) {
            const buttonHtml = `
                <input type="button" class="submit-display-result" 
                    data-person-id="${personId}"
                    data-geraet-id="${geraetId}"
                    data-run="${i}"
                    value="Ergebnis anzeigen (Run ${i})">`;
            $container.append(buttonHtml);
        }
        $container.find('.submit-display-result[data-run="1"]').val('Ergebnis anzeigen (Run 1)');
    } else if (targetCount < currentCount) {
        for (let i = currentCount; i > targetCount; i--) {
            $container.find(`.submit-display-result[data-run="${i}"]`).remove();
        }
        if (targetCount === 1 && $container.find('.submit-display-result').length === 1) {
            $container.find('.submit-display-result').val('Ergebnis anzeigen');
        }
    }

    $container.find('.submit-display-result').each(function() {
        $(this).attr('data-person-id', personId);
    });
    
}

$.fn.updateCurrentEdit = function() {
  return this.each(function() {
	  const $input = $(this);

	  const url = '/intern/scripts/kampfrichter/ajax/ajax-kampfrichter_currentedit.php';

      if ($input.attr('data-person-id') === "0"){
        $('<form>', {
            action: '/intern/kampfrichter',
            method: 'post'
        })
        .append($('<input>', {
            type: 'hidden',
            name: 'next_subabt',
            value: 1
        }))
        .append($('<input>', {
            type: 'hidden',
            name: 'next_subabt_submit',
            value: '>'
        }))
        .append($('<input>', {
            type: 'hidden',
            name: 'csrf_token',
            value: csrf_token
        }))
        .appendTo('body')
        .submit();
      }

	  fetch(url, {
		  method: 'POST',
		  headers: {'Content-Type': 'application/x-www-form-urlencoded'},
		  body: new URLSearchParams({
			  csrf_token,
			  editId: $input.attr('data-person-id'),
			  geraet: $input.attr('data-geraet-id') ?? null
		  })
	  })
		  .then(res => res.json())
		  .then(response => {
		  if (response.success) {
            
            $(".current-turnerin-name").css({
                'color': '#209200ff',
                'transition': 'all 0.3s ease-out'
            });

            setTimeout(() => $(".current-turnerin-name").css({
                'color': ''
            }), 2000);

            $(".div_edit_values_user").css("display", "flex");

            $(".heading_fv_selturnerin")[0].scrollIntoView();

            $(".current-turnerin-name").text(response.titel);

            $(".fv_nextturnerin").text(response.nturnerin?.name ?? '');
            $(".fv_nextturnerin").val(response.nturnerin?.id ?? 0).attr('data-person-id', response.nturnerin?.id ?? 0);

            $(".submit-display-turnerin").css("opacity", "1");
            $(".submit-display-start").css("opacity", "1");
            $(".submit-display-result").css("opacity", "1");

            const $editAllDiv = $('.div_edit_values_all_gereate');
            const noten = response.noten; 
            const personId = response.id;
            const programmId = response.programm_id;

            $editAllDiv.find(`.submit-display-turnerin`).closest('.all_vaules_div').addClass('hidden');

            // 1. Loop directly through the 'noten' object
            for (const [geraetId, disciplineData] of Object.entries(noten)) {
                
                // Find the specific DOM wrapper for this Geraet using the outer div
                // Assuming your PHP renders the tables with the correct geraetId on the button
                const $disciplineWrapper = $editAllDiv.find(`.submit-display-turnerin[data-geraet-id="${geraetId}"]`).closest('.all_vaules_div');
                
                if ($disciplineWrapper.length === 0) continue;

                $disciplineWrapper.removeClass('hidden');

                // --- UPDATE GENERAL BUTTONS FOR THIS GERAET ---
                $disciplineWrapper.find(".submit-display-turnerin, .submit-display-start").attr({
                    'data-person-id': personId,
                    'data-geraet-id': geraetId
                });

                $disciplineWrapper.find(".submit-musik-start, .submit-musik-stopp").attr({
                    'data-id': personId,
                    'data-geraet': geraetId
                });

                // 2. Identify master containers for this specific discipline
                const $masterContainer = $disciplineWrapper.find('.singleNotentable').first();
                const $displayresultDiv = $disciplineWrapper.find('.div-submit-display-result');

                $masterContainer.find('.note-container').addClass('hidden');
                
                // 3. CLEANUP: Remove previously generated runs and buttons
                $disciplineWrapper.find('.singleNotentable').not(':first').remove();
                $displayresultDiv.find('.submit-display-result').not(':first').remove();

                const $originalResultBtn = $displayresultDiv.find('.submit-display-result').first();
                $displayresultDiv.find('.submit-display-result').addClass('hidden');
                const runKeys = Object.keys(disciplineData).sort((a, b) => a - b);
                const totalRuns = runKeys.length;

                // 4. Process each Run in the data
                runKeys.forEach(runNum => {
                    const runInt = parseInt(runNum);
                    let $currentRunContainer;

                    if (runInt === 1) {
                        $currentRunContainer = $masterContainer;
                    } else {
                        // CLONE the entire container for Run 2, 3, etc.
                        $currentRunContainer = $masterContainer.clone();
                        $currentRunContainer.addClass(`run-container-block run-${runNum}`);
                        $currentRunContainer.insertAfter($disciplineWrapper.find('.singleNotentable').last());
                    }



                    // 5. Update all Tables and Inputs inside this Run Container
                    for (const [noteId, value] of Object.entries(disciplineData[runNum])) {
                        const $table = $currentRunContainer.find(`.note-container[data-note-id="${noteId}"]`);
                        $table.removeClass('hidden');
                        
                        // Update Header to show Run Number
                        if (runInt > 1) {
                            const $header = $table.find('.note-name-header');
                            if (!$header.find('.rm-tag').length) {
                                $header.append(` <span class="rm-tag" style="font-size: 0.8em;">(R${runNum})</span>`);
                            }
                        }

                        // Update Input attributes and value
                        const $input = $table.find('input');
                        $input.attr({
                            'data-run': runNum,
                            'data-person-id': personId,
                            'data-geraet-id': geraetId,
                            'data-programm-id': programmId
                        }).val(value ?? '');
                    }

                    // 6. Remove tables cloned from Run 1 that don't exist in Run 2+
                    if (runInt > 1) {
                        $currentRunContainer.find('input[data-run="1"]').closest('.note-container').remove();
                    }
                });

                // Ensure the UI script tracking the buttons is updated last
                updateRunButtons(totalRuns, personId, $displayresultDiv);
            }

        

            //$(".submit-display-result").attr('data-person-id', response.id);

		  } else {
			  displayMsg(0, response.message);
			  $input.css({
				  'background-color': '#f8d7da',
				  'color': '#fff',
				  'transition': 'all 0.3s ease-out'
			  });
			  setTimeout(() => $input.css({
				  'background-color': '',
				  'color': ''
			  }), 2000);
		  }
	  })
		  .catch(err => {
		  $input.css('background-color', '#f8d7da');
		  console.error('AJAX fetch error:', err);
	  });
  });
};

function getRandomInt(max) {
  return Math.floor(Math.random() * max);
}

jQuery(document).ready(function($) {

    
    $('.editTurnerin').on('click', function() {
        $(this).updateCurrentEdit();
    });

    const $ajaxInputDiv = $('.div_edit_values_all_gereate');

	
    $ajaxInputDiv.on('change', '.ajax-input', function(e) {
        const $input = $(this);
        
        const url = `/intern/scripts/kampfrichter/ajax/ajax-update_value_kampfrichter.php`;

        personId = $input.attr('data-person-id');
        fieldTypeId = $input.attr('data-field-type-id');
        programmId = $input.attr('data-programm-id');
        gereatId = $input.attr('data-geraet-id');
        runNum = $input.attr('data-run') || 1;
        jahr = window.AKTUELLES_JAHR;
        value = $input.val();

        fetch(url, {
                method: 'POST',
                headers: {'Content-Type': 'application/x-www-form-urlencoded'},
                body: new URLSearchParams({
                    csrf_token,
                    personId: personId,
                    fieldTypeId: fieldTypeId,
                    gereatId: gereatId,
                    run: runNum,
                    jahr: jahr,
                    value: value
                })
            })
            .then(res => res.json())
            .then(response => {

                if (response.success) {
                
                    let objValues = [];

                    const rowId = $input.attr('data-id');

                    $input.css({"color": "#0e670d", "font-weight": "600"});

                
                    setTimeout(() => $input.css({'color': '', "font-weight": ""}), 2000);

                    const noten = response.noten;

                    for (const [keyG, noteGroup] of Object.entries(noten)) {
                        for (const [key, runGroup] of Object.entries(noteGroup)) {
                            for (const [run, value] of Object.entries(runGroup)) {

                                const $elements = $(`.changebleValue[data-field-type-id="${key}"][data-geraet-id="${keyG}"][data-person-id="${personId}"][data-run="${run}"]`);

                                $elements.each((ind, el) => {
                                    const $el = $(el);
                                    
                                    if ($el.is('input')) {
                                        $el.val(value ?? '');
                                    } else {
                                        const isNullable = ($el.attr('data-noten-nullable') ?? 'false') === 'true';
                                        const floatValZero = parseFloat(value.replace(",", ".").replace("'", "")) === 0.0;

                                        let hasValue = false;

                                        if (isNullable && floatValZero || value === '') {
                                            $el.text('-').addClass('emtyPlaceholder');
                                        } else {
                                            $el.text(value).removeClass('emtyPlaceholder');
                                            hasValue = true;
                                        }

                                        updateDependentVisibility($el, hasValue);
                                    }
                                });
                            }
                        }
                    }
                    

                    if (selecteddiscipline === 'A') {
                        const event = new CustomEvent('valueChanged', { 
                            detail: { 
                                noten: noten, 
                                programmId: programmId, 
                                personId: personId 
                            } 
                        });

                        window.dispatchEvent(event);
                    }

                    if (wsOpen) {
                        ws.send(JSON.stringify({
                            type: "KAMPFRICHTER_UPDATE",
                            payload: {
                                discipline: window.FREIGABE,
                                gereatId: gereatId,
                                personId: personId,
                                programmId: programmId,
                                jahr: jahr,
                                noten: noten
                            }
                        }));
                    }
                    
                    } else {
                        // Flash red on error
                        $input.css({'color': '#ff6a76ff'});
                        displayMsg(0, response.message || 'Unknown error');
                        console.error(response.message || 'Unknown error');
                    }
            })
            .catch(err => {
                $input.css({'color': '#670d0d'});
                console.error('AJAX fetch error:', err);
            });
    });

    $('.submit-display-turnerin').on('click', function() {
            const $input = $(this);
            const geraetId = $input.attr('data-geraet-id');
        
            // Build the URL with GET parameters safely
            const url = '/intern/scripts/kampfrichter/ajax/displays/ajax-display-functions.php';
        
            fetch(url,{
                method: 'POST',
                headers: {'Content-Type': 'application/x-www-form-urlencoded'},
                body: new URLSearchParams({
                    csrf_token,
                    personId: $input.attr('data-person-id'),
                    geraetId,
                    jahr: window.AKTUELLES_JAHR,
                    type: "neu"
                })
            })
                .then(res => res.json())
                .then(response => {
        
                    if (response.success) {
                        if (wsOpen) {
                            ws.send(JSON.stringify({
                                type: "UPDATE_SCORE",
                                payload: {
                                    geraet: response.nameGeraet,
                                    geraetId,
                                    data: response.data
                                }
                            }));
                        } else {
                            displayMsg(2, 'Keine live Syncrosation, Verzögerungen');
                        }
                        displayMsg(1, 'Neue Person wird angezigt');

                        $input.css('opacity', 0.5);
                  } else {
                      displayMsg(0, response.message);
                  }
                })
                .catch(err => {
                    $input.css('background-color', '#f8d7da');
                    displayMsg(0, 'AJAX fetch error:' + err);
                    console.error('AJAX fetch error:', err);
                });
        });

    $('.submit-display-start').on('click', function() {
            const $input = $(this);
            const geraetId = $input.attr('data-geraet-id');
            const personId = $input.attr('data-person-id')
        
            const url = '/intern/scripts/kampfrichter/ajax/displays/ajax-display-functions.php';
            const dataType = $input.attr('data-type');
        
            fetch(url,{
                method: 'POST',
                headers: {'Content-Type': 'application/x-www-form-urlencoded'},
                body: new URLSearchParams({
                    csrf_token,
                    geraetId,
                    personId,
                    dataType: dataType,
                    type: "start"
                })
            })
                .then(res => res.json())
                .then(response => {
        
                    if (response.success) {
                        if (wsOpen) {
                            ws.send(JSON.stringify({
                                type: "UPDATE_SCORE",
                                payload: {
                                    geraet: response.nameGeraet,
                                    geraetId,
                                    data: response.data
                                }
                            }));
                        } else {
                            displayMsg(2, 'Keine live Syncrosation, Verzögerungen');
                        }

                        if (dataType == 1) {
                            displayMsg(1, 'Start freigegeben');
                        } else if (dataType == 0) {
                            displayMsg(1, 'Startfreigabe entzogen');
                        }
                        

                  } else {
                        displayMsg(0, response.message);
                  }
                })
                .catch(err => {
                    $input.css('background-color', '#f8d7da');
                    displayMsg(0, 'AJAX fetch error:' + err);
                    console.error('AJAX fetch error:', err);
                });
        });

    
    $('.submit-musik-start').on('click', function() {
            const $input = $(this);
            const geraetId = $input.attr('data-geraet-id');

            // Build the URL with GET parameters safely
            const url = `/intern/scripts/kampfrichter/ajax/ajax-update_kampfrichter_start_musik.php`;
        
            fetch(url,{
                method: 'POST',
                headers: {'Content-Type': 'application/x-www-form-urlencoded'},
                body: new URLSearchParams({
                    csrf_token,
                    personId: $input.attr('data-id'),
                    geraetId
                })
            })
                .then(res => res.json())
                .then(response => {
                    if (wsOpen) {
                        ws.send(JSON.stringify({
                            type: "AUDIO",
                            payload: {
                                audioDiscipline: geraetId
                            }
                        }));
                    } else {
                        displayMsg(2, 'Keine live Syncrosation, Verzögerungen');
                    }
        
                    if (response.success) {
                        displayMsg(1, 'Musik wird abgespielt werden');
                  } else {
                      displayMsg(0, 'Error: ' + response.message);
                  }
                })
                .catch(err => {
                    $input.css('background-color', '#f8d7da');
                    displayMsg(0, 'AJAX fetch error:' + err);
                    console.error('AJAX fetch error:', err);
                });
        });

    $('.submit-musik-stopp').on('click', function() {
        const $input = $(this);
        const geraetId = $input.attr('data-geraet-id');

        // Build the URL with GET parameters safely
        const url = `/intern/scripts/kampfrichter/ajax/ajax-update_kampfrichter_stopp_musik.php`;
    
        fetch(url,{
            method: 'POST',
            headers: {'Content-Type': 'application/x-www-form-urlencoded'},
            body: new URLSearchParams({
                csrf_token,
                geraetId
            })
        })
            .then(res => res.json())
            .then(response => {
                if (response.success) {
                    if (wsOpen) {
                        ws.send(JSON.stringify({
                            type: "AUDIO",
                            payload: {
                                audioDiscipline: geraetId
                            }
                        }));
                    } else {
                        displayMsg(2, 'Keine live Syncrosation, Verzögerungen');
                    }
                    displayMsg(1, 'Musik wird gestoppt werden');
                } else {
                    alert('Error: ' + response.message);
                }
            })
            .catch(err => {
                $input.css('background-color', '#f8d7da');
                displayMsg(0, 'AJAX fetch error:' + err);
                console.error('AJAX fetch error:', err);
            });
    });

    $('.div-submit-display-result').on('click', '.submit-display-result', function() {
        $input = $(this);
        const geraetId = $input.attr('data-geraet-id');
        const personId = $input.attr('data-person-id');

        // Build the URL with GET parameters safely
        const url = '/intern/scripts/kampfrichter/ajax/displays/ajax-display-functions.php';
    
        fetch(url,{
            method: 'POST',
            headers: {'Content-Type': 'application/x-www-form-urlencoded'},
            body: new URLSearchParams({
                csrf_token,
                personId,
                geraetId,
                run: $input.attr("data-run"),
                jahr: window.AKTUELLES_JAHR,
                type: "result"
            })
        })
            .then(res => res.json())
            .then(response => {
    
            if (response.success) {
                if (wsOpen) {
                    ws.send(JSON.stringify({
                        type: "UPDATE_SCORE",
                        payload: {
                            geraetId,
                            geraet: response.nameGeraet,
                            data: response.data
                        }
                    }));
                    ws.send(JSON.stringify({
                        type: "UPDATE_RANKLIVE_SCORE",
                        payload: {
                            geraetId,
                            personId,
                            jahr: window.AKTUELLES_JAHR,
                            rankLive: response.rankLive
                        }
                    }));
                } else {
                    displayMsg(2, 'Keine live Syncrosation, Verzögerungen');
                }
                $input.css('opacity', 0.5);
                displayMsg(1, 'Resultat wird angezeigt');
            } else {
                alert('Error: ' + response.message);
            }
        })
        .catch(err => {
            $input.css('background-color', '#f8d7da');
            displayMsg(0, 'AJAX fetch error:' + err);
            console.error('AJAX fetch error:', err);
        });
    });
});

function updateDependentVisibility($changedEl, hasValue = false) {
    const uid = $changedEl.attr('data-uid');
    if (uid === undefined || uid === null) return;

    const $row = $changedEl.closest('tr');

    if ($row.length !== 1) return;

    const isVisible = $changedEl.hasClass('emtyPlaceholder');
    const doesExist = $changedEl.hasClass('nonExistentEl');

    const $linkedEls = $row.find(`.singleValueSpan[data-linked-el-uid="${uid}"]`);

    $linkedEls.each((ind, el) => {
        const $linkedEl = $(el);
        if (!hasValue) {
            hasValue = $linkedEl.hasClass('changebleValue') && $linkedEl.text().trim() !== '-';
        }

        $linkedEl.toggleClass('emtyPlaceholder', (isVisible && !hasValue)).toggleClass('nonExistentEl', doesExist);

        const linkedElUid = $linkedEl.data('linked-el-uid');

        const $subLinkedEls = $row.find(`.singleValueSpan[data-linked-el-uid="${linkedElUid}"]`);

        if ($subLinkedEls.length > 0)  updateDependentVisibility($linkedEl);
    });
}

function initConditionalVisibility() {
    const $table = $('table.customDisplayEditorTable');

    const $rows = $table.find('tr');

    $rows.each((ind, el) => {
        const $row = $(el);
        $row.find('.singleValueSpan[data-linked-el-uid]').each(function() {

            const linkedUid = $(this).data('linked-el-uid');
            
            const $linkedEl = $row.find(`.singleValueSpan[data-uid="${linkedUid}"]`);
            
            if ($linkedEl.length === 1) {
                updateDependentVisibility($linkedEl);
            }
        });
    })
    
}

initConditionalVisibility();
initConditionalVisibility();

const selecteddiscipline = window.FREIGABE;

ws.addEventListener("message", event => { // Use 'event' as it's more standard than 'blob'
  let msgOBJ;

  try {
    msgOBJ = JSON.parse(event.data);
  } catch (error) {
    return;
  }

  // Ensure it's an UPDATE type (matches your sendToGroup logic)
  if (msgOBJ?.type === "UPDATE") {
    const data = msgOBJ.payload;
    
    // Check access rights
    if (data.discipline === selecteddiscipline.toLowerCase() || selecteddiscipline === 'A') {
        const noten = data.noten;

        for (const [keyG, noteGroup] of Object.entries(noten)) {
            for (const [key, runGroup] of Object.entries(noteGroup)) {

                for (const [run, value] of Object.entries(runGroup)) {

                    // Select all matching elements (inputs and spans)
                    const $elements = $(`.changebleValue[data-field-type-id="${key}"][data-geraet-id="${keyG}"][data-person-id="${data.personId}"][data-run="${run}"]`);

                    $elements.each((ind, el) => {
                        const $el = $(el);
                        
                        if ($el.is('input')) {
                            $el.val(value ?? '');

                            // Visual feedback: Flash color
                            const nativeEl = $el[0];
                            nativeEl.style.transition = 'color 0.3s';
                            nativeEl.style.color = '#008e85';
                            
                            setTimeout(() => {
                                nativeEl.style.color = '';
                            }, 1000);
                        } else {
                            const isNullable = ($el.attr('data-noten-nullable') ?? 'false') === 'true';
                            const floatValZero = parseFloat(value.replace(",", ".").replace("'", "")) === 0.0;

                            let hasValue = false;

                            if (isNullable && floatValZero || value === '') {
                                $el.text('-').addClass('emtyPlaceholder');
                            } else {
                                $el.text(value).removeClass('emtyPlaceholder');
                                hasValue = true;
                            }

                            updateDependentVisibility($el, hasValue);
                            
                            $el.removeClass('updated');
                            $el.addClass('updated');
                            
                            setTimeout(() => {
                                $el.removeClass('updated');
                            }, 2000);
                        }
                    });
                }
            }
        }
    }
  }
});
