<?php

ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);

if (!isset($baseDir)) {
    $baseDir = $_SERVER['DOCUMENT_ROOT'];
}

require_once $baseDir . '/../scripts/session_functions.php';

ini_wkvs_session(true);

$csrf_token = $_SESSION['csrf_token'] ?? '';

$access_granted_wkl = check_user_permission('wk_leitung', true) ?? false;

if (!$access_granted_wkl):

    $logintype = 'wk_leitung';

    require $baseDir . '/../scripts/login/login.php';

    $logintype = '';

else:
?>
<!DOCTYPE html>
<html lang="de">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="icon" type="png" href="/intern/img/icon.png">
    <title>WK-leitung - Rank Live</title>


    <link rel="stylesheet" href="/intern/css/rank-live.css">
    <link rel="stylesheet" href="/intern/css/sidebar.css">
    <script src="/intern/js/jquery/jquery-3.7.1.min.js"></script>
    <script src="/intern/js/jquery/jquery-ui.min.js"></script>
    <script src="/intern/js/jquery/jquery.ui.touch-punch.min.js"></script>
    <script src="/intern/js/custom-msg-display.js"></script>
    <link rel="stylesheet" href="/intern/css/custom-msg-display.css">
    <link rel="stylesheet" href="/intern/css/custom-select.css">
    <link rel="stylesheet" href="/files/fonts/fonts.css">
    <link rel="stylesheet" href="/intern/css/user.css">

    <link rel="stylesheet" href="/intern/css/coloris/coloris.min.css" />
    <script src="/intern/js/coloris/coloris.min.js"></script>

</head>

<body class="einstellungen">
    <?php


        require $baseDir . '/../scripts/db/db-functions.php';
        require $baseDir . '/../scripts/db/db-tables.php';

        require $baseDir . '/../scripts/websocket/ws-create-token.php';


        $type = 'wkl';

        $dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';

        if ($dbconnection['success'] !== true) {
            echo 'Critical DB Error.';
            exit;
        }

        $currentPage = 'rankLive';

        require $baseDir . '/../scripts/sidebar/sidebar.php';

        $active_slug = $_SESSION['current_ranklive_slug'] ?? 'rankLive-overview';

        $allNotenTypes = db_select($mysqli, $db_tabelle_wertungstypen, "name, id, anzahl_laeufe_json");
        $indexed_noten = array_column($allNotenTypes, "name", "id");

        $geraeteDB = db_select($mysqli, $db_tabelle_disziplinen, "id, name");
        $geraete = array_column($geraeteDB, "name", "id");
        $geraete[0] = 'Pseudogerät für Berechnung';
        $total_geraete_count = count($geraete) - 1;

        $programme_db = db_select($mysqli, $db_tabelle_kategorien, "id, programm");
        $programme = array_column($programme_db, "programm", "id");
        $total_programs_count = count($programme);

        $all_program_ids = array_keys($programme); 

        $options_note = [];
        $options_note_s_geraet = [];

        foreach ($allNotenTypes as $s_note) {
            $id = $s_note['id'];
            $anzahl_laeufe_array = json_decode($s_note['anzahl_laeufe_json'] ?? '', true) ?? [];
            $default = intval($anzahl_laeufe_array['default'] ?? 1);

            $runs_per_device = [];

            foreach ($geraete as $g_id => $s_geraet) {
                $sub_default = $anzahl_laeufe_array[$g_id]['all'] ?? $default;
                $is_g_specific = isset($anzahl_laeufe_array[$g_id]['all']);

                foreach ($programme as $p_id => $s_prog) {
                    $is_p_specific = isset($anzahl_laeufe_array[$g_id][$p_id]) && !is_array($anzahl_laeufe_array[$g_id][$p_id]);
                    $k = $is_p_specific ? intval($anzahl_laeufe_array[$g_id][$p_id]) : $sub_default;
                    
                    if ($k < 1) continue;
                    if ($g_id === 0 && !($is_p_specific || $is_g_specific)) continue;

                    for ($i = 1; $i <= $k; $i++) {
                        $options_note[$id][$g_id][$i][$p_id] = 1;
                    }
                }

                $runs_per_device[$g_id] = isset($options_note[$id][$g_id]) ? count($options_note[$id][$g_id]) : 0;
            }

            if (isset($options_note[$id])) {
                foreach ($options_note[$id] as $g_id => $g_array) {
                    foreach ($g_array as $run => $run_array) {
                        if (count($run_array) === $total_programs_count) {
                            $options_note[$id][$g_id][$run] = ['A'];
                        }
                    }
                }
            }

            $max = max($runs_per_device);
            for ($i = 1; $i <= $max; $i++) {
                foreach ($runs_per_device as $g_id => $run_c) {
                    if ($run_c < $i) continue; 
                    $options_note_s_geraet[$id][$i][$g_id] = 1;
                }
            }

            if (isset($options_note_s_geraet[$id])) {
                foreach ($options_note_s_geraet[$id] as $run => $g_array) {
                    $has_zero = isset($g_array[0]);
                    $expected_count = $has_zero ? $total_geraete_count + 1 : $total_geraete_count;
                    
                    if (count($g_array) === $total_geraete_count && !$has_zero) {
                        $options_note_s_geraet[$id][$run] = 'A';
                    }
                }
            }
        }

        $getGeraetName = function($id) use ($geraete) {
            return $geraete[$id] ?? '';
        };



        $allOptions = [
            'text' => [
                'text' => 'Eigener statischer Text'
            ],
            'personData' => [
                'geburtsdatum' => 'Geburtsdatum',
                'jahrgang' => 'Jahrgang',
                'name' => 'Name',
                'vorname' => 'Vorname',
                'verein' => 'Verein',
                'programm' => 'Programm'
            ],
            'sortData' => [
                'rang' => 'Rang',
                'startindex' => 'Startreihenfolge'
            ],
            'layoutEls' => [
                'vertical' => 'Vertical'
            ],
            'kampfrichterEls' => [
                'edit' => 'Bearbeitungsicon'
            ],
            'notenData' => $options_note,
            'notenGeraetData' => $options_note_s_geraet
        ];

        $allOprionsNameArray = [
            'text' => 'Statischer Text',
            'personData' => 'Personendaten',
            'sortData' => 'Rangdaten',
            'notenData' => 'Noten',
            'notenGeraetData' => 'Noten',
            'layoutEls' => 'Layout Elemente',
            'kampfrichterEls' => 'Elemente Kampfrichter'
        ];

        $jsonstr = db_select($mysqli, $db_tabelle_tabellen_konfiguration, 'json', 'type_slug = ?', [$active_slug], '', 1);

        $allowed_types = [
            'rankLive-overview'   => ["name" => 'RankLive Overview', 'geraet' => 'all', 'type' => 'rankLive'], 
            'rankLive-geraet'     => ["name" => 'RankLive einzelnes Gerät', 'geraet' => 'single', 'type' => 'rankLive'],
            'kampfrichter-admin'  => ["name" => 'Kampfrichter Admin (alle Geräte)', 'geraet' => 'all', 'type' => 'kampfrichter'],
            'kampfrichter-geraet' => ["name" => 'Kampfrichter einzelnes Gerät', 'geraet' => 'single', 'type' => 'kampfrichter'],
            'rangliste'           => ["name" => 'Rangliste', 'geraet' => 'all', 'type' => 'indev']
        ];

        // 2. Decode JSON into an associative array
        $data = json_decode($jsonstr[0]['json'] ?? '', true) ?? [];

        $headers = $data['header'] ?? [];
        $bodyColumns = $data['body'] ?? [];

        function ipn($input)
        {
            global $programme;
            return $programme[$input] ?? '';
        }

        $lindex = 0;
        $highest_uid = 0;

        function constructSingleValueSpan($token, $type) {
            global $lindex;
            global $highest_uid;
            $lindex++;
            $text = $token['text'] ?? '';
            $uid = (int) ($token['uid'] ?? 0);

            if ($uid > $highest_uid) $highest_uid = $uid;

            $classes = 'singleValueSpan ui-sortable-handle dragable';
            $extraAttributes = '';
            $boldString = '';
            $minDisplayWidth = $token['minDisplayWidth'] ?? 0;
            $dataAttributes = 'data-min-display-width="' . $minDisplayWidth . '" data-uid="' . $uid . '" data-type="' . htmlspecialchars($type) . '"';
            $style = '';

            

            if ($type !== 'kampfrichterEls') {
                $bold = $token['bold'] ?? false;
                $font_size = $token['fontSize'] ?? 0;
                $linked_el_uid = $token['linkedElUid'] ?? 0;

                if ($font_size > 0) {
                    $style = ' style="font-size: ' . (int)$font_size . 'px"';
                }

                $boldString = ($bold === true || $bold === 'true') ? 'true' : 'false';
                $dataAttributes .= ' data-bold="' . $boldString . '" data-linked-el-uid="' . $linked_el_uid . '"';
            }

            

            switch ($type) {
                case 'text':
                    $classes .= ' staticText';
                    $dataAttributes .= ' data-column="' . htmlspecialchars($token['column'] ?? 'text') . '"';
                    break;

                case 'kampfrichterEls':
                    $dataAttributes .= ' data-column="' . htmlspecialchars($token['column'] ?? 'text') . '"';
                    break;

                case 'personData':
                    $dataAttributes .= ' data-column="' . htmlspecialchars($token['column'] ?? '') . '"';
                    
                    if (($token['column'] ?? '') === 'geburtsdatum') {
                        $dataAttributes .= ' data-php-date-format="' . htmlspecialchars($token['phpDateFormat'] ?? '') . '"';
                    }
                    break;

                case 'notenData':
                    $dataAttributes .= ' data-field-type-id="' . htmlspecialchars($token['field-type-id'] ?? '') . '"';
                    $dataAttributes .= ' data-geraet-id="' . htmlspecialchars($token['geraet-id'] ?? '') . '"';
                    $dataAttributes .= ' data-run="' . htmlspecialchars($token['run'] ?? '') . '"';
                    $dataAttributes .= ' data-programm-ids="' . htmlspecialchars($token['programm-ids'] ?? '') . '"';

                    $notenNullable = $token['notenNullable'] ?? false;
                    $notenNullableStr = ($notenNullable === 'true' || $notenNullable === true) ? 'true' : 'false';
                    $dataAttributes .= ' data-noten-nullable="' . $notenNullableStr . '"';
                    break;

                case 'notenGeraetData':
                    $dataAttributes .= ' data-field-type-id="' . htmlspecialchars($token['field-type-id'] ?? '') . '"';
                    $dataAttributes .= ' data-run="' . htmlspecialchars($token['run'] ?? '') . '"';

                    $notenNullable = $token['notenNullable'] ?? false;
                    $notenNullableStr = ($notenNullable === 'true' || $notenNullable === true) ? 'true' : 'false';
                    $dataAttributes .= ' data-noten-nullable="' . $notenNullableStr . '"';
                    break;

                case 'sortData':
                    $dataAttributes .= ' data-column="' . htmlspecialchars($token['column'] ?? '') . '"';
                    break;
            }
            ?>
            <span class="<?= $classes; ?>" <?= $dataAttributes; ?><?= $extraAttributes; ?><?= $style ?>>
                <span class="textSingleValueSpan"><?= htmlspecialchars($text) ?></span>

                <div class="settingsDivSingleValueSpan hidden">
                    <?php if ($type === 'text') : ?>
                        <div class="settingsInputGroup">
                            <label for="statischerTextInput-<?= $lindex ?>">Text:</label>
                            <input type="text" 
                                id="statischerTextInput-<?= $lindex ?>" 
                                class="statischerTextInput" 
                                placeholder="Statischer Text" 
                                value="<?= htmlspecialchars($text) ?>">
                        </div>
                    <?php elseif ($type === 'notenData' || $type === 'notenGeraetData') : ?>
                        <div class="settingsInputGroup">
                            <label for="nullNotenCheckbox-<?= $lindex ?>">Wert 0.00 <b>nicht</b> anzeigen?</label>
                            <label class="checkbox">
                                <input type="checkbox" 
                                    id="nullNotenCheckbox-<?= $lindex ?>" 
                                    class="nullNotenCheckbox" 
                                    <?= ($notenNullable === 'true' || $notenNullable === true) ? 'checked' : '' ?>>
                                <span class="checkbox-ui"></span>
                            </label>
                        </div>
                    <?php elseif ($type === 'personData' && ($token['column'] ?? '') === 'geburtsdatum') : ?>
                        <div class="settingsInputGroup">
                            <label for="gebutsdatumFormatInput-<?= $lindex ?>"><a href="https://www.php.net/manual/de/datetime.format.php#:~:text=format,-Das" target="_blank">PHP-Datumsformat</a></label>
                                <div class="autocomplete-container">
                                    <input type="text" id="gebutsdatumFormatInput-<?= $lindex ?>" class="gebutsdatumFormatInput" value="<?= htmlspecialchars($token['phpDateFormat'] ?? '') ?>" placeholder="d. MMMM YYYY">
                                    <div id="dropdownList" class="dropdown-list hidden"></div>
                                </div>
                        </div>
                    <?php endif; ?>

                    <?php if ($type !== 'kampfrichterEls') : ?>
                        <div class="settingsInputGroup">
                            <label for="boldCheckbox-<?= $lindex ?>">Fetter Text:</label>
                            <label class="checkbox">
                                <input type="checkbox" 
                                    id="boldCheckbox-<?= $lindex ?>" 
                                    class="boldCheckbox" 
                                    <?= ($bold === 'true' || $bold === true) ? 'checked' : '' ?>>
                                <span class="checkbox-ui"></span>
                            </label>
                        </div>

                        <div class="settingsInputGroup">
                            <label for="inputFontSize-<?= $lindex ?>">Schriftgrösse</label>
                            <label for="inputFontSize-<?= $lindex ?>" class="inputLabelWrapper">
                                <input type="number" 
                                        min="1"
                                        id="inputFontSize-<?= $lindex ?>" 
                                        class="inputFontSize"
                                        placeholder="16"
                                        value="<?= ($font_size > 0) ? (int)$font_size : ''?>">
                                <span>px</span>
                            </label>
                            
                        </div>

                        <div class="settingsInputGroup">
                            <label for="inputDisplayOnDisplayWidth-<?= $lindex ?>">Minimale Bildschirmbreite</label>
                            <label for="inputDisplayOnDisplayWidth-<?= $lindex ?>" class="inputLabelWrapper">
                                <input type="number"
                                        placeholder="Kein Limit"  
                                        class="inputDisplayOnDisplayWidth" 
                                        id="inputDisplayOnDisplayWidth-<?= $lindex ?>"
                                        value="<?= intval($minDisplayWidth) ?>">
                                <span>px</span>
                            </label>
                        </div>

                        <div class="settingsInputGroup">
                            <label for="inputConditionalDisplay-<?= $lindex ?>">Conditional Display</label>
                            <button type="button" id="inputConditionalDisplay-<?= $lindex ?>" class="inputConditionalDisplay">
                                Element auswählen…
                            </button>
                            <span class="spanConditionalDisplay"></span>
                        </div>
                    <?php endif; ?>

                    <div class="settingsInputGroup">
                        <label for="deleteSingleValueSpan-<?= $lindex ?>">Löschen</label>
                        <button type="button" 
                                id="deleteSingleValueSpan-<?= $lindex ?>" 
                                class="deleteSingleValueSpan">X</button>
                    </div>
                </div>
                <span class="settingSpan">
                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
                        <path d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1a8.45 8.45 0 0 0-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3-1.57-3-3.5s1.07-3.5 3-3.5 3 1.57 3 3.5-1.07 3.5-3 3.5z"></path>
                    </svg>
                </span>
            </span>
        <?php }

        ?>
        <section class="bgSection">
            <?php sidebarRender('modal'); ?>
            <div class="headerDivTrainer">
                <div class="headingPanelDiv">
                    <h2 class="headingPanel">Konfiguration RankLive</h2>
                </div>
                <div class="menuWrapper">
                    <?php sidebarRender('button'); ?>
                </div>
            </div>

            <div class="dashboardGrid">
            <div class="selectSlugType">
                    <div class="customSelect customSelectSlugType" id="selectedOptionSlugType" data-value="">
                        <button type="button" id="selectTriggerSlugType" class="selectTrigger paddingNormal" aria-expanded="false">
                            <span class="selectLabel"><?= $allowed_types[$active_slug]['name'] ?? '' ?></span>
                            <svg class="selectArrow" xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none'
                                height="14" width="14">
                                <path d='M6 9L12 15L18 9' stroke='currentColor' stroke-width='2' stroke-linecap='round'
                                    stroke-linejoin='round' />
                            </svg>
                        </button>
                        <ul class="selectOptions">

                            <?php foreach ($allowed_types as $s_type => $s_type_data): ?>
                                <?php $selected = ($s_type === $active_slug) ? 'selected' : ''; ?>
                                <li data-value="<?= htmlspecialchars($s_type) ?>" data-type="<?= htmlspecialchars($s_type_data['type']) ?>" data-geraet="<?= htmlspecialchars($s_type_data['geraet']) ?>" class="<?= $selected ?>"><?= htmlspecialchars($s_type_data['name']) ?></li>
                            <?php endforeach; ?>

                        </ul>
                    </div>
                </div>
                <div class="contentDiv">
                    <table class="mainTable">
                        <thead>
                            <tr id="headerRowRankLiveConfig">
                                <?php foreach ($headers as $header_data): ?>
                                    <?php 
                                    $minDisplayWidth = intval($header_data['minDisplayWidth'] ?? 0);
                                    $lindex++; 
                                    ?>
                                    <th class="headerThRankLiveConfig" data-min-display-width="<?= $minDisplayWidth ?>">
                                        <span>
                                            <input class="columnTitleInput" placeholder="Spaltenüberschrift" value="<?= htmlspecialchars($header_data['title']) ?>">
                                            <span class="deleteColumnBtn">X</span>
                                            <span class="addColumnBtn addColumnBtnAfter">+</span>
                                            <span class="addColumnBtn addColumnBtnBefore">+</span>
                                            <div class="settingsDivSingleValueSpan hidden">

                                                <div class="settingsInputGroup">
                                                    <label for="inputDisplayOnDisplayWidth-<?= $lindex ?>">Minimale Bildschirmbreite</label>
                                                    <label for="inputDisplayOnDisplayWidth-<?= $lindex ?>" class="inputLabelWrapper">
                                                        <input type="number"
                                                                placeholder="Kein Limit"  
                                                                class="inputDisplayOnDisplayWidth" 
                                                                id="inputDisplayOnDisplayWidth-<?= $lindex ?>"
                                                                value="<?= intval($minDisplayWidth) ?>">
                                                        <span>px</span>
                                                    </label>
                                                </div>
                                            </div>
                                            <span class="settingSpan">
                                                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
                                                    <path d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1a8.45 8.45 0 0 0-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3-1.57-3-3.5s1.07-3.5 3-3.5 3 1.57 3 3.5-1.07 3.5-3 3.5z"></path>
                                                </svg>
                                            </span>
                                        </span>
                                    </th>
                                <?php endforeach; ?>
                            </tr>
                        </thead>
                        <tbody>
                            <tr id="bodyRowRankLiveConfig">
                                <?php foreach ($bodyColumns as $columnTokens): ?>
                                    <td>
                                        <span class="rankLiveFieldContainer dragableDropArea">
                                            <span class="addFieldBtn">+</span>

                                            <?php

                                            foreach ($columnTokens as $token) {
                                                $type = $token['type'] ?? '';
                                                if ($type === 'layoutEls') :
                                                    $column = $token['column'];
                                                    $content = $token['content'] ?? []; ?>
                                                    <div class="<?= $column ?>LayoutEl dragable" data-type="<?= $type ?>" data-column="<?= $column ?>">
                                                        <?php foreach ($content as $row) : ?>
                                                            <span class="dragableDropArea <?= $column ?>LayoutElRow">
                                                                <?php foreach ($row as $el) :
                                                                    constructSingleValueSpan($el, $el['type']);
                                                                endforeach; ?>
                                                            </span>
                                                        <?php endforeach; ?>
                                                    </div>
                                                <?php else:
                                                    constructSingleValueSpan($token, $type);
                                                endif;
                                            }

                                            ?>
                                                
                                        </span>
                                    </td>
                                <?php endforeach; ?>
                            </tr>
                        </tbody>
                    </table>
                    <button id="addColumn" class="blackBtn <?= count($headers) > 0 ? 'hidden' : '' ?>">Spalte hinzufügen</button>
                    <label for="importConfig" class="blackBtn">Tablelle importieren</label>
                    <input id="importConfig" type="file" class="hidden" accept=".json, .wkvs">
                    <button id="exportConfig" class="blackBtn">Gespeicherte Tablelle exportieren</button>
                    <button id="saveConfig" class="blackBtn">Tablelle speichern</button>
                </div>
                <div class="inDevDiv">Dieses Feature befindet sich zurzeit noch in Entwicklung</div>
            </div>

            <div class="customSelect customSelectAddOption hidden" id="selectedOption" data-value="">
                <button type="button" id="selectTrigger" class="selectTrigger paddingNormal" aria-expanded="false">
                    <span class="selectLabel placeholder">Bitte auswählen…</span>
                    <svg class="selectArrow" xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none'
                        height="14" width="14">
                        <path d='M6 9L12 15L18 9' stroke='currentColor' stroke-width='2' stroke-linecap='round'
                            stroke-linejoin='round' />
                    </svg>
                </button>
                <ul class="selectOptions">

                    <?php foreach ($allOptions as $sNotenGroupName => $sNotenGroup): ?>
                        <div class="singleOptionDiv <?= $sNotenGroupName ?>">
                            <li class="customSelectSubGroupHeader"><?= $allOprionsNameArray[$sNotenGroupName] ?></li>
                            <ul class="customSelectSubGroup">
                                <?php foreach ($sNotenGroup as $key => $sNote): ?>
                                    <?php if ($sNotenGroupName === 'notenData'): ?>
                                        <?php foreach ($sNote as $g_id => $n_array_gerate): ?>
                                            <?php foreach ($n_array_gerate as $run => $n_array_run): ?>

                                                <?php

                                                $has_all_progs = !(is_array($n_array_run) && !(isset($n_array_run[0]) && $n_array_run[0] === 'A'));
                                                $displayed_progs = $has_all_progs ? '' : ' (nur ' . implode(', ', array_map('ipn', array_keys($n_array_run))) . ')';
                                                $data_progs = $has_all_progs ? 'A' : '[' . implode(', ', array_keys($n_array_run)) . ']';
                                                $runs = count($n_array_gerate) > 1 ? ' (Run ' . $run . ')' : '';
                                                $geraet = (intval($g_id) !== 0) ? ', ' . ($geraete[$g_id] ?? 'INTERNAL ERROR') : '';

                                                ?>

                                                <li data-field-type-id="<?= $key ?>" data-type="<?= $sNotenGroupName ?>"
                                                    data-geraet-id="<?= $g_id ?>" data-run="<?= $run ?>" data-programm-ids="<?= $data_progs ?>"
                                                    class=""><?= $indexed_noten[$key] ?><?= $geraet ?><?= $runs ?><?= $displayed_progs ?></li>

                                            <?php endforeach; ?>
                                        <?php endforeach; ?>
                                    <?php elseif ($sNotenGroupName === 'notenGeraetData'):
                                        $note_name = $indexed_noten[$key] ?? '';
                                        $multiple_runs = count($sNote) > 1;

                                        foreach ($sNote as $run => $run_geraete):

                                            $run_text = ($multiple_runs) ? " R". $run : '';
                                            $geraete_text = (is_array($run_geraete) && !empty($run_geraete)) ? " (nur " . implode(", ", array_map($getGeraetName, array_keys($run_geraete))) . ")" : "";

                                            ?>

                                            <li data-field-type-id="<?= $key ?>" data-type="<?= $sNotenGroupName ?>"
                                                data-run="<?= $run ?>"
                                                class=""><?= $note_name ?><?= $run_text ?><?= $geraete_text ?></li>

                                        <?php endforeach; ?>
                                    <?php else: ?>
                                        <li data-column="<?= $key ?>" data-type="<?= $sNotenGroupName ?>" class=""><?= $sNote ?></li>
                                    <?php endif; ?>
                                <?php endforeach; ?>
                            </ul>
                        </div>
                    <?php endforeach; ?>

                </ul>
            </div>

            <div class="msgDiv"></div>

        </section>

        <script>

            const arrayWSSend = [
                ''
            ];

            let $activeEl = null;
            let active_type_slug = '<?= $active_slug ?>';
            let currentUid = <?= $highest_uid + 1 ?>;

            const $customSelectColumns = $('.customSelectAddOption');
            const $headerRow = $('#headerRowRankLiveConfig');
            const $bodyRow = $('#bodyRowRankLiveConfig');
            const csrf_token = "<?= $csrf_token ?>";

            $(document).on('click', '.selectTrigger', function (e) {
                e.stopPropagation();
                $(this).closest('.customSelect').toggleClass('open');
            });

            function setDropdownWidth() {
                const $container = $('.customSelectAddOption'); 

                const $dropdown = $container.children('.selectOptions');
                
                const width = $dropdown.outerWidth(); 
                    
                if (width === 0) width = 100; 
                $container.outerWidth(width);
            }

            const $uids = $('.singleValueSpan:not([data-uid="0"])');

            const arrayUids = $uids.map(function() {
                return parseInt($(this).data('uid'), 10) || 0;
            }).get();

            let currentCheckId = arrayUids.length > 0 ? Math.max(...arrayUids) + 1 : 1;

            function getNextAvailableUid() {
                let candidateId = currentCheckId;
                
                while (arrayUids.includes(candidateId)) {
                    candidateId++;
                }

                arrayUids.push(candidateId);

                currentCheckId = candidateId + 1;
                
                return candidateId;
            }

            function setNullUids() {
                const $targetEls = $('.singleValueSpan[data-uid="0"]');
                if ($targetEls.length < 1) return;

                $targetEls.each((index, el) => {
                    $(el).attr('data-uid', getNextAvailableUid());
                });
            }

            setNullUids();

            function setDropdownPosition(el) {
                const $button = $(el);
            
                const $td = $button.closest('td');
                
                if ($td.length === 0) {
                    console.error("Could not find parent <td> element.");
                    return;
                }

                let pos = $td.offset();
                const $tdHeightOffset = $td.outerHeight() + 5;

                pos.top = pos.top + $tdHeightOffset;
                pos.left = pos.left - 1;

                $('.customSelectAddOption').css({
                    top: pos.top,
                    left: pos.left
                }).data('button', el);
            }

            $(window).on('resize', function() {
                let reference = $('.customSelectAddOption').data('button') ?? null;

                if (reference === null) return;

                const $reference = $(reference);

                const $td = $reference.closest('td');
                
                if ($td.length === 0) {
                    console.error("Could not find parent <td> element.");
                    return;
                }

                let pos = $td.offset();
                const $tdHeightOffset = $td.outerHeight() + 5;

                pos.top = pos.top + $tdHeightOffset;
                pos.left = pos.left - 1;

                $('.customSelectAddOption').css({
                    top: pos.top,
                    left: pos.left
                })
            })

            const $table = $('mainTable');

            function settingsSvg() {
                return $('<span></span>').addClass('settingSpan').html('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1a8.45 8.45 0 0 0-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3-1.57-3-3.5s1.07-3.5 3-3.5 3 1.57 3 3.5-1.07 3.5-3 3.5z"/></svg>');
            }

            function generateTh() {
                const $newTh = $("<th></th>").addClass('headerThRankLiveConfig');

                const $newThSpan = $("<span></span>");

                const $deleteBtn = $("<span></span>").text("X").addClass('deleteColumnBtn');

                const $addSpanAfter = $("<span></span>").text("+").addClass('addColumnBtn addColumnBtnAfter').data("insert", "after");
                const $addSpanBefore = $("<span></span>").text("+").addClass('addColumnBtn addColumnBtnBefore').data("insert", "before");

                const $input = $('<input>').attr('placeholder', 'Spaltenüberschrift').addClass('columnTitleInput');

                const $div = $('<div></div>').addClass('settingsDivSingleValueSpan hidden');

                /*const $boldDiv = $('<div></div>').addClass('settingsInputGroup');
                const $label1 = $('<label></label>').text('Fetter Text:').attr('for', `boldCheckbox-${lindex}`);
                const $input1 = createCheckbox('boldCheckbox', `boldCheckbox-${lindex}`);
                $boldDiv.append($label1, $input1);

                const $fontSizeDiv = $('<div></div>').addClass('settingsInputGroup');
                const $labelFontSize = $('<label></label>').text('Schriftgrösse').attr('for', `inputFontSize-${lindex}`);
                const $inputFontSize = $('<input>').attr('placeholder', '16').attr("type", "number").addClass('inputFontSize').attr('id', `inputFontSize-${lindex}`).attr("min", "1");
                const $pxSpanFontSize = $('<span></span>').text('px');
                const $labelWraperFontSize = $('<label></label>').class("inputLabelWrapper").attr('for', `inputFontSize-${lindex}`);
                $labelWraperFontSize.append($inputFontSize, $pxSpanFontSize);
                $fontSizeDiv.append($labelFontSize, $labelWraperFontSize);*/

                const $mobileDiv = $('<div></div>').addClass('settingsInputGroup');
                const $labelM = $('<label></label>').text('Minimale Bildschirmbreite').attr('for', `inputDisplayOnDisplayWidth-${lindex}`);
                const $inputM = $('<input>').attr('placeholder', 'Kein Limit').attr("type", "number").addClass('inputDisplayOnDisplayWidth').attr('id', `inputDisplayOnDisplayWidth-${lindex}`);
                const $pxSpan = $('<span></span>').text('px');
                const $labelWraper = $('<label></label>').addClass("inputLabelWrapper").attr('for', `inputDisplayOnDisplayWidth-${lindex}`);
                $labelWraper.append($inputM, $pxSpan);
                $mobileDiv.append($labelM, $labelWraper);

                $div.append($mobileDiv);

                $newThSpan.append($input, $deleteBtn, $addSpanAfter, $addSpanBefore, $div, settingsSvg());

                $newTh.append($newThSpan);

                return $newTh;
            }

            function generateTd() {
                const $td = $('<td></td>');

                const $span = $('<span></span>').addClass('rankLiveFieldContainer dragableDropArea');

                const $addbtn = $('<span></span>').text("+").addClass("addFieldBtn");

                $span.append($addbtn);

                $td.append($span);

                return $td;
            }

            $('body').on('click', '.addFieldBtn', function (e) {
                $activeEl = $(this).parent();
                
                const prevEl = $customSelectColumns.data("last-el") ?? $('body')[0];

                if (prevEl === this) {
                    $customSelectColumns.toggleClass('hidden');
                } else {
                    $customSelectColumns.removeClass('hidden');
                }

                $customSelectColumns.data("last-el", this);

                if (!$customSelectColumns.hasClass('hidden')) {
                    setDropdownWidth();
                    setDropdownPosition(this);
                }
            });

            $('#addColumn').on('click', function (e) {
                $headerRow.append(generateTh());

                $bodyRow.append(generateTd());
                $(this).addClass('hidden');
                safeRefreshSortable();
            });

            $('body').on('click', '.addColumnBtn', function (e) {

                const $el = $(this);

                const insert = $el.data("insert") ?? '';
                const index = $el.closest('th').index();

                const $newTh = generateTh();

                const $existingItemAtIndexHeader = $headerRow.children().eq(index);

                if ($existingItemAtIndexHeader.length > 0) {

                    if (insert === "before") { $existingItemAtIndexHeader.before($newTh); }
                    else { $existingItemAtIndexHeader.after($newTh); }

                } else {
                    $headerRow.append($newTh);
                }

                const $existingItemAtIndexBody = $bodyRow.children().eq(index);

                const $newTd = generateTd();

                if ($existingItemAtIndexBody.length > 0) {

                    if (insert === "before") { $existingItemAtIndexBody.before($newTd); }
                    else { $existingItemAtIndexBody.after($newTd); }

                } else {
                    $bodyRow.append($newTd);
                }

                safeRefreshSortable();
            });

            $headerRow.sortable({
                connectWith: "#headerRowRankLiveConfig",
                items: ".headerThRankLiveConfig",
                placeholder: "dropPlaceholderColumn",
                helper: "clone",
                appendTo: "body",
                tolerance: "pointer",

                start: function(e, ui) {
                    const elementWidth = ui.item.outerWidth() - 4;
                    const elementHeight = ui.item.outerHeight() - 4;
                    const oldindex = ui.item.index();
                    ui.item.data('old-index', oldindex);

                    ui.placeholder.width(elementWidth);
                    ui.placeholder.height(elementHeight);
                },

                stop: function(e, ui) {
                    const oldIndex = ui.item.data('old-index');
                    const newIndex = ui.item.index();

                    if (oldIndex === undefined || oldIndex === newIndex) return;

                    const $container = $('#bodyRowRankLiveConfig');
                    const $targetTd = $container.children().eq(oldIndex);

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

                    if (newIndex > oldIndex) {
                        $targetTd.insertAfter($container.children().eq(newIndex));
                    } else {
                        $targetTd.insertBefore($container.children().eq(newIndex));
                    }
                }

            }).disableSelection();

            function safeRefreshSortable() {
                $(".dragableDropArea").each(function () {
                    if ($(this).data("ui-sortable") || $(this).data("sortable")) {
                        $(this).sortable("refresh");
                    } else {
                        $(this).sortable({
                            connectWith: ".dragableDropArea",
                            items: ".dragable",
                            placeholder: "dropPlaceholder",
                            helper: "clone",
                            appendTo: "body",
                            tolerance: "intersect",

                            start: function(e, ui) {
                                const elementWidth = ui.item.outerWidth() - 4;
                                const elementHeight = ui.item.outerHeight() - 4;

                                ui.placeholder.width(elementWidth);
                                ui.placeholder.height(elementHeight);
                            }
                        }).disableSelection();
                    }
                });
            }

            safeRefreshSortable();

            let lindex = <?= $lindex ?? 0 ?>;

            function createCheckbox(className, id, isChecked = false) {

                const $label = $('<label>', { class: 'checkbox' });

                const $input = $('<input>', {
                    type: 'checkbox',
                    id: id,
                    class: className
                });

                if (isChecked) {
                    $input.prop('checked', true);
                }

                const $span = $('<span>', { class: 'checkbox-ui' });

                return $label.append($input).append($span);
            }

            function settingsDiv(type) {
                lindex ++;
                const $div = $('<div></div>').addClass('settingsDivSingleValueSpan hidden');
                
                switch (type) {
                    case "text":
                        const $sdiv1 = $('<div></div>').addClass('settingsInputGroup');
                        const $slabel1 = $('<label></label>').text('Text:').attr('for', `statischerTextInput-${lindex}`);
                        const $sinput1 = $('<input>').attr('placeholder', 'Statischer Text').addClass('statischerTextInput').attr('id', `statischerTextInput-${lindex}`);
                        $sdiv1.append($slabel1, $sinput1);
                        $div.append($sdiv1);
                        break;
                    case "notenData":
                    case "notenGeraetData":
    
                        const $sdiv2 = $('<div></div>').addClass('settingsInputGroup');
                        const $slabel2 = $('<label></label>').html('Wert 0.00 <b>nicht</b> anzeigen?').attr('for', `nullNotenCheckbox-${lindex}`);
                        const $sinput2 = createCheckbox('nullNotenCheckbox', `nullNotenCheckbox-${lindex}`);
                        $sdiv2.append($slabel2, $sinput2);
                        $div.append($sdiv2);
                        break;
                }

                if (type !== 'kampfrichterEls') {

                    const $boldDiv = $('<div></div>').addClass('settingsInputGroup');
                    const $label1 = $('<label></label>').text('Fetter Text:').attr('for', `boldCheckbox-${lindex}`);
                    const $input1 = createCheckbox('boldCheckbox', `boldCheckbox-${lindex}`);
                    $boldDiv.append($label1, $input1);
    
                    const $fontSizeDiv = $('<div></div>').addClass('settingsInputGroup');
                    const $labelFontSize = $('<label></label>').text('Schriftgrösse').attr('for', `inputFontSize-${lindex}`);
                    const $inputFontSize = $('<input>').attr('placeholder', '16').attr("type", "number").addClass('inputFontSize').attr('id', `inputFontSize-${lindex}`).attr("min", "1");
                    const $pxSpanFontSize = $('<span></span>').text('px');
                    const $labelWraperFontSize = $('<label></label>').addClass("inputLabelWrapper").attr('for', `inputFontSize-${lindex}`);
                    $labelWraperFontSize.append($inputFontSize, $pxSpanFontSize);
                    $fontSizeDiv.append($labelFontSize, $labelWraperFontSize);
    
                    const $mobileDiv = $('<div></div>').addClass('settingsInputGroup');
                    const $labelM = $('<label></label>').text('Minimale Bildschirmbreite').attr('for', `inputDisplayOnDisplayWidth-${lindex}`);
                    const $inputM = $('<input>').attr('placeholder', 'Kein Limit').attr("type", "number").addClass('inputDisplayOnDisplayWidth').attr('id', `inputDisplayOnDisplayWidth-${lindex}`);
                    const $pxSpan = $('<span></span>').text('px');
                    const $labelWraper = $('<label></label>').addClass("inputLabelWrapper").attr('for', `inputDisplayOnDisplayWidth-${lindex}`);
                    $labelWraper.append($inputM, $pxSpan);
                    $mobileDiv.append($labelM, $labelWraper);

                    const $conditionalFormatingDiv = $('<div></div>').addClass('settingsInputGroup');
                    const $labelCD = $('<label></label>').text('Conditional Display').attr('for', `inputConditionalDisplay-${lindex}`);
                    const $inputCD = $('<button></button>').text('Element auswählen…').attr('type', 'button').addClass('inputConditionalDisplay').attr('id', `inputConditionalDisplay-${lindex}`);
                    const $selectedElSpan = $('<span></span>').addClass('spanConditionalDisplay');
                    $conditionalFormatingDiv.append($labelCD, $inputCD, $selectedElSpan);

                    $div.append($boldDiv, $fontSizeDiv, $conditionalFormatingDiv, $mobileDiv);
                }

                const $removeDiv = $('<div></div>').addClass('settingsInputGroup');
                const $labelR = $('<label></label>').text('Löschen').attr('for', `deleteSingleValueSpan-${lindex}`);
                const $inputR = $('<button></button>').text('X').addClass('deleteSingleValueSpan').attr('id', `deleteSingleValueSpan-${lindex}`);
                $removeDiv.append($labelR, $inputR);


                $div.append($removeDiv);

                return $div;
            }

            $(document).on('click', '.boldCheckbox', function () {
                const $el = $(this);
                const $parent = $el.closest('.singleValueSpan');
                if ($parent.length !== 1) return;
                const oldValue = $parent.attr('data-bold') ?? false;
                const oldBool = oldValue === true || oldValue === 'true';
                $parent.attr('data-bold', !oldBool);
            });

            $(document).on('click', '.nullNotenCheckbox', function () {
                const $el = $(this);
                const $parent = $el.closest('.singleValueSpan');
                if ($parent.length !== 1) return;
                const oldValue = $parent.attr('data-noten-nullable') ?? false;
                const oldBool = oldValue === true || oldValue === 'true';
                $parent.attr('data-noten-nullable', !oldBool);
            });

            $(document).on('input', '.statischerTextInput', function () {
                const $el = $(this);
                const val = $el.val();
                const $target = $el.closest('.singleValueSpan').children(".textSingleValueSpan");
                if ($target.length !== 1) return;
                $target.html(val);
            });

            $(document).on('input', '.inputFontSize', function () {
                const $el = $(this);
                const val = parseInt($el.val(), 10) || 0;
                const $parent = $el.closest('.singleValueSpan');
                if ($parent.length !== 1) return;
                $parent.data('font-size', val);
                const $textSpan = $parent.children('.textSingleValueSpan');
                if ($textSpan.length !== 1) return;
                if (val === 0) {
                    $textSpan.css('font-size', '');
                } else {
                    $textSpan.css('font-size', val + 'px');
                }
            }); 

            $(document).on('input', '.gebutsdatumFormatInput', function () {
                const $el = $(this);
                const val = $el.val();
                const $parent = $el.closest('.singleValueSpan');
                if ($parent.length !== 1) return;
                $parent.data('php-date-format', val);
            });

            $(document).on('input', '.singleValueSpan .inputDisplayOnDisplayWidth', function () {
                const $el = $(this);
                const val = $el.val();
                const $parent = $el.closest('.singleValueSpan');
                if ($parent.length !== 1) return;
                $parent.attr('data-min-display-width', val);
            });

            $(document).on('input', 'th .inputDisplayOnDisplayWidth', function () {
                const $el = $(this);
                const val = $el.val();
                const $parent = $el.closest('th');
                if ($parent.length !== 1) return;
                $parent.attr('data-min-display-width', val);
            });

            $(document).on('click', '.settingSpan', function (e) {
                const $el = $(this);
                const $targetEl = $el.siblings('.settingsDivSingleValueSpan');
                if ($targetEl.length > 0) {
                    $targetEl.toggleClass('hidden');
                    $('.settingsDivSingleValueSpan').not($targetEl).addClass('hidden');
                } else {
                    $('.settingsDivSingleValueSpan').addClass('hidden');
                }
            });

            function toggleSortable(bool) {
                const sortableText = bool ? "disable" : "enable";
                $(".dragableDropArea").each(function () {
                    if ($(this).data("ui-sortable") || $(this).data("sortable")) {
                        $(this).sortable(sortableText);
                    }
                });
            }

            $(document).on('click', '.inputConditionalDisplay', function (e) {
                const $btn = $(this);
                const $table = $('table.mainTable');
                if ($table.length !== 1) return;

                const $container = $btn.closest('.singleValueSpan');

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

                $container.toggleClass('condEl');
                $table.toggleClass('selectCondEl');

                const tableHasClass = $table.hasClass('selectCondEl');
                toggleSortable(tableHasClass);

                $('.selectedCondEl').removeClass('selectedCondEl');

                const savedNativeElUid = $container.attr('data-linked-el-uid') || false;
                if (savedNativeElUid) {
                    const $oldSelectedEl = $table.find(`.singleValueSpan[data-uid=${savedNativeElUid}]`);
                    if ($oldSelectedEl.length === 1) {
                        $oldSelectedEl.addClass('selectedCondEl');
                    }
                }

                if (tableHasClass) {
                    $table.on('click.condDisplay', '.singleValueSpan:not(.condEl)', function(e2) {
                        const $clickedSpan = $(e2.target).closest('.singleValueSpan');

                        if ($clickedSpan.length !== 1) return;
                        
                        $container.attr('data-linked-el-uid', $clickedSpan.attr('data-uid'));
                        
                        $table.removeClass('selectCondEl');
                        $container.removeClass('condEl');
                        toggleSortable(false);
                        
                        $table.off('click.condDisplay', '.singleValueSpan:not(.condEl)');
                    });
                } else {
                    $table.off('click.condDisplay', '.singleValueSpan:not(.condEl)');
                }
            });

            $(document).on('click', '.deleteSingleValueSpan', async function (e) {
                const $el = $(this);
                const $targetEl = $el.closest('.singleValueSpan');

                if (!await displayConfirm("Feld löschen?")) return;

                if ($targetEl.length > 0) {
                    $targetEl.remove();
                }
            });


            $(document).on('click', '.customSelectAddOption .selectOptions li', function (e) {
                e.stopPropagation();
                const $item = $(this);
                const $container = $item.closest('.customSelect');
                const text = $item.text();
                const $input = $container.find('.selectValue');
                const $textInput = $container.find('.selectText') ?? [];
                const $typeInput = $container.find('.selectType') ?? [];
                const $geraetInput = $container.find('.selectGeraet') ?? [];
                const $label = $container.find('.selectLabel');
                const $allOptions = $container.find('.selectOptions li');

                $allOptions.removeClass('selected');

                $input.trigger('change');
                $container.removeClass('open');

                const type = $item.data("type") ?? null;

                if (type === 'layoutEls') {
                    const $newDiv = $('<div></div>');
                    const dataColumn = $item.data("column") ?? null;
                    $newDiv.attr("data-column", dataColumn).attr("data-type", type).addClass('dragable');

                    switch (dataColumn) {
                        case 'vertical':
                            $newDiv.addClass('verticalLayoutEl');
                            const $dropSpan = $('<span></span>').addClass('dragableDropArea verticalLayoutElRow');
                            $newDiv.append($dropSpan, $dropSpan.clone())
                            break;
                    }
                    $activeEl.append($newDiv);
                } else {
                    $span = $('<span></span>').addClass('singleValueSpan dragable').attr("data-type", type).attr('data-uid', getNextAvailableUid());
                    currentUid++;

                    const $textSpan = $('<span></span>').text(text).addClass('textSingleValueSpan');

                    if (type === 'notenData') {
                        $span.attr("data-geraet-id", $item.data("geraet-id") ?? null);
                        $span.attr("data-field-type-id", $item.data("field-type-id") ?? null);
                        $span.attr("data-run", $item.data("run") ?? null);
                        $span.attr("data-programm-ids", $item.data("programm-ids") ?? null);
                    } else if (type === 'notenGeraetData') {
                        $span.attr("data-field-type-id", $item.data("field-type-id") ?? null);
                        $span.attr("data-run", $item.data("run") ?? null);
                    } else {
                        $span.attr("data-column", $item.data("column") ?? null);
                    }


                    if (type === 'text') {
                        $span.addClass('staticText');
                    }

                    $span.append($textSpan, settingsDiv(type), settingsSvg());
                    $activeEl.append($span);
                }


                $activeEl = null;

                $customSelectColumns.addClass('hidden');

                safeRefreshSortable();
            });

            $(document).on('click', () => $('.customSelect').removeClass('open'));

            $(document).on('click', function (event) {
                const clickedInsideProtected = $(event.target).closest('.settingSpan, .settingsDivSingleValueSpan, .settingsInputGroup').length > 0;

                if (clickedInsideProtected) {
                    return;
                }

                $('.settingsDivSingleValueSpan').addClass('hidden');
            });

            $('body').on('click', '.deleteColumnBtn', async function () {

                if (!await displayConfirm("Spalte löschen?")) return;

                const $el = $(this);
                const $th = $el.closest('th');

                const index = $th.index();

                const $existingItemAtIndex = $('#bodyRowRankLiveConfig').children().eq(index);

                if ($existingItemAtIndex.length < 1) {
                    displayMsg(0, "Fehler");
                    return;
                }

                $th.remove();
                $existingItemAtIndex.remove();
                showAddBtnOnEmtyHeader();
            });

            function showAddBtnOnEmtyHeader() {
                if ($('#headerRowRankLiveConfig').children('th').length < 1) $('#addColumn').removeClass('hidden');
            }

            function generateTargetDataForEl($target, type) {
                
                const minDisplayWidth = parseInt($target.attr('data-min-display-width') ?? 0, 10) || 0;
                const elUid = parseInt($target.attr('data-uid') ?? 0, 10) || 0;

                let targetData = {
                    type: type,
                    text: $target.children('.textSingleValueSpan').text(),
                    minDisplayWidth,
                    uid: elUid
                };

                if (type !== 'kampfrichterEls') {
                    const bold = $target.attr('data-bold') ?? false;
                    const fontSize = parseInt($target.data('font-size') ?? 0, 10) || 0;
                    const condElUid = parseInt($target.attr('data-linked-el-uid') ?? 0, 10) || 0;
                    targetData["bold"] = bold;
                    targetData["fontSize"] = fontSize;
                    targetData["linkedElUid"] = condElUid;
                }


                switch (type) {
                    case "notenData":
                        targetData["field-type-id"] = $target.data('field-type-id');
                        targetData["geraet-id"] = $target.data("geraet-id");
                        targetData["run"] = $target.data('run');
                        targetData["programm-ids"] = $target.data("programm-ids");
                        targetData["notenNullable"] = $target.attr("data-noten-nullable") ?? "false";
                        break;

                    case "notenGeraetData":
                        targetData["field-type-id"] = $target.data('field-type-id');
                        targetData["run"] = $target.data('run');
                        targetData["notenNullable"] = $target.attr("data-noten-nullable") ?? "false";
                        break;

                    case "text":
                        targetData.content = $target.data('column');
                        break;

                    case "kampfrichterEls":
                        targetData.content = $target.data('column');
                        break;

                    case "sortData":
                        targetData.column = $target.data('column');
                        break;

                    case "personData":
                        targetData.column = $target.data('column');

                        if ($target.data('column') === 'geburtsdatum') {
                            targetData["phpDateFormat"] = $target.data('php-date-format') ?? '';
                        }
                        break;

                    default:
                        return null;
                }
                return targetData;
            }

            function saveTable() {
                const $headerRow = $('#headerRowRankLiveConfig');
                const $bodyRow = $('#bodyRowRankLiveConfig');

                const $headerColumns = $headerRow.children('th');
                const $bodyColumns = $bodyRow.children('td');

                let json = {
                    header: [],
                    body: []
                };

                $.each($headerColumns, function (index, el) {
                    const $header = $(el);
                    const $input = $header.find(".columnTitleInput");
                    const val = $input.val() || '';
                    const minDisplayWidth = parseInt($header.attr('data-min-display-width') ?? 0, 10) || 0;
                    let targetData = {
                        title: val,
                        minDisplayWidth
                    }
                    json.header.push(targetData);
                });

                $.each($bodyColumns, function (index, el) {
                    const $targets = $(el).children(".rankLiveFieldContainer").children(":not(.addFieldBtn)");

                    json.body[index] = [];

                    if ($targets.length > 0) {
                        $.each($targets, function (tindex, tel) {
                            const $target = $(tel);
                            const type = $target.data('type');

                            let targetData = {};

                            if (type === 'layoutEls') {
                                targetData = {
                                    type,
                                    column: $target.attr("data-column"),
                                    content: []
                                };
                                const $rows = $target.children(".verticalLayoutElRow");
                                
                                $.each($rows, function (rindex, trow) {
                                    targetData['content'][rindex] = []; 
                                    
                                    const $row_targets = $(trow).children(".singleValueSpan");
                                    $.each($row_targets, function (trowindex, trowel) {
                                        const $trowel = $(trowel);
                                        const trowelType = $trowel.data('type');
                                        const subres = generateTargetDataForEl($trowel, trowelType);
                                        if (subres === null) return null;
                                        targetData['content'][rindex][trowindex] = subres;
                                    });
                                });
                            } else {
                                targetData = generateTargetDataForEl($target, type);
                                if (targetData === null) return null;
                            }
                            
                            json.body[index].push(targetData);
                        });
                    }
                });

                const jsonstr = JSON.stringify(json);

                return jsonstr;
            }

            $('#saveConfig').on('click', function () {
                const json = saveTable();

                if (json === null) {
                    displayMsg(0, "Fehler beim Konertieren der RankLive Tabelle");
                    return;
                }

                $.ajax({
                    url: '/intern/scripts/ranklive/ajax-save-ranklive-config.php',
                    method: 'POST',
                    data: {
                        csrf_token,
                        slug: active_type_slug,
                        json: json
                    },
                    success: function (response) {
                        if (typeof response === "string") {
                            response = response ? JSON.parse(response) : {};
                        }

                        if (response.success) {
                            displayMsg(1, "OK");
                        } else {
                            displayMsg(2, response.message || "Unbekannter Fehler");
                        }
                    },
                    error: function (xhr, status, errorThrown) {
                        displayMsg(0, "Fehler");
                        console.error(xhr);
                    }
                });
            });

            function loadTable(jsonInput) {
                let json;
                try {
                    json = typeof jsonInput === "string" ? JSON.parse(jsonInput) : jsonInput;
                } catch (e) {
                    console.error("Invalid JSON provided to loadTable:", e);
                    return false;
                }

                if (!json || !json.header || !json.body) {
                    console.error("JSON layout structure is missing header or body blocks.");
                    return false;
                }

                const $headerRow = $('#headerRowRankLiveConfig');
                const $bodyRow = $('#bodyRowRankLiveConfig');

                $headerRow.empty();
                $bodyRow.empty();

                $('#addColumn').addClass('hidden');

                $.each(json.header, function (index, headerData) {
                    const $th = generateTh();
                    
                    $th.find('.columnTitleInput').val(headerData.title || '');
                    
                    if (headerData.minDisplayWidth) {
                        $th.attr('data-min-display-width', headerData.minDisplayWidth);
                        $th.find('.inputDisplayOnDisplayWidth').val(headerData.minDisplayWidth);
                    }
                    
                    $headerRow.append($th);
                });

                $.each(json.body, function (index, columnItems) {
                    const $td = generateTd();
                    const $container = $td.find('.rankLiveFieldContainer');
                    const $addBtn = $container.find('.addFieldBtn');

                    if (columnItems && columnItems.length > 0) {
                        $.each(columnItems, function (tindex, itemData) {
                            let $element;

                            if (itemData.type === 'layoutEls') {
                                $element = $('<div></div>')
                                    .attr("data-column", itemData.column)
                                    .attr("data-type", 'layoutEls')
                                    .addClass('dragable');
                                    
                                if (itemData.column === 'vertical') {
                                    $element.addClass('verticalLayoutEl');
                                }
                                
                                if (itemData.content && Array.isArray(itemData.content)) {
                                    $.each(itemData.content, function (rindex, rowItems) {
                                        const $dropSpan = $('<span></span>').addClass('dragableDropArea verticalLayoutElRow');
                                        
                                        if (rowItems && Array.isArray(rowItems)) {
                                            $.each(rowItems, function (trowindex, subItemData) {
                                                const $subEl = generateSingleValueSpanFromData(subItemData);
                                                if ($subEl) $dropSpan.append($subEl);
                                            });
                                        }
                                        $element.append($dropSpan);
                                    });
                                }
                            } else {
                                $element = generateSingleValueSpanFromData(itemData);
                            }

                            if ($element) {
                                $addBtn.before($element);
                            }
                        });
                    }

                    $bodyRow.append($td);
                });

                showAddBtnOnEmtyHeader();
                safeRefreshSortable();
                
                return true;
            }

            // Internal functional helper to systematically convert a single data object back to a DOM node
            function generateSingleValueSpanFromData(data) {
                if (!data || !data.type) return null;

                const type = data.type;
                const elUid = data.uid || 0;
                const $span = $('<span></span>').addClass('singleValueSpan dragable').attr("data-type", type).attr("data-uid", elUid);
                const $textSpan = $('<span></span>').text(data.text || '').addClass('textSingleValueSpan');
                
                // Leverage your existing DOM generator to keep control tracking context unique (lindex)
                const $settings = settingsDiv(type);

                // Reconstruct Global Layout/Styling Properties
                if (data.bold === true || data.bold === 'true') {
                    $span.attr('data-bold', 'true');
                    $settings.find('.boldCheckbox').prop('checked', true);
                }
                
                if (data.fontSize) {
                    const fontSizeVal = parseInt(data.fontSize, 10) || 0;
                    $span.data('font-size', fontSizeVal);
                    $textSpan.css('font-size', fontSizeVal + 'px');
                    $settings.find('.inputFontSize').val(fontSizeVal);
                }

                if (data.minDisplayWidth) {
                    const minWidthVal = parseInt(data.minDisplayWidth, 10) || 0;
                    $span.attr('data-min-display-width', minWidthVal);
                    $settings.find('.inputDisplayOnDisplayWidth').val(minWidthVal);
                }

                if (data.linkedElUid) {
                    const linkedElUid = parseInt(data.linkedElUid, 10) || 0;
                    $span.attr('data-linked-el-uid', linkedElUid);
                }

                // Reconstruct Context-Specific Metadata Properties
                switch (type) {
                    case "notenData":
                    case "notenGeraetData":
                        const zeroNotenCheck = data["notenNullable"] === true || data["notenNullable"] === 'true';
                        $span.attr("data-noten-nullable", zeroNotenCheck ? "true" : "false");
                        $settings.find('.nullNotenCheckbox').prop('checked', zeroNotenCheck);
                        
                    case "notenData":
                        $span.attr("data-geraet-id", data["geraet-id"] ?? null);
                        $span.attr("data-field-type-id", data["field-type-id"] ?? null);
                        $span.attr("data-run", data["run"] ?? null);
                        $span.attr("data-programm-ids", data["programm-ids"] ?? null);
                        break;

                    case "notenGeraetData":
                        $span.attr("data-field-type-id", data["field-type-id"] ?? null);
                        $span.attr("data-run", data["run"] ?? null);
                        break;

                    case "text":
                        $span.attr("data-column", data.content ?? null);
                        $span.addClass('staticText');
                        $settings.find('.statischerTextInput').val(data.text || '');
                        break;

                    case "kampfrichterEls":
                        $span.attr("data-column", data.content ?? null);
                        break;

                    case "personData":
                        $span.attr("data-column", data.column ?? null);
                        if (data["phpDateFormat"]) {
                            $span.data('php-date-format', data["phpDateFormat"]);
                            $settings.find('.gebutsdatumFormatInput').val(data["phpDateFormat"]);
                        }
                        break;
                        
                    case "sortData":
                        $span.attr("data-column", data.column ?? null);
                        break;
                }

                $span.append($textSpan, $settings, settingsSvg());
                return $span;
            }

            const $contentDiv = $('.contentDiv');
            const $inDevDiv = $('.inDevDiv');

            function configureAddOptionDropdown(type, geraet) {
                
                if (type === 'indev' || type === 'rangliste') {
                    $contentDiv.addClass('hidden');
                    $inDevDiv.removeClass('hidden');
                    return;
                }

                $contentDiv.removeClass('hidden');
                $inDevDiv.addClass('hidden');

                const $selectOptions = $customSelectColumns.find(".selectOptions");
                if ($selectOptions.length !== 1) return;
                
                const $sectionNotenAllData = $selectOptions.find('div.notenData');
                const $sectionNotenGeraetData = $selectOptions.find('div.notenGeraetData');

                if ($sectionNotenAllData.length !== 1 || $sectionNotenGeraetData.length !== 1) return;

                const geraetAll = geraet === 'all';

                $sectionNotenAllData.toggleClass('hidden', !geraetAll);
                $sectionNotenGeraetData.toggleClass('hidden', geraetAll);
            }

            configureAddOptionDropdown('<?= $allowed_types[$active_slug]['type'] ?>', '<?= $allowed_types[$active_slug]['geraet'] ?>');

            $(document).on('click', '.customSelectSlugType .selectOptions li', function (e) {
                e.stopPropagation();
                const $item = $(this);
                const $container = $item.closest('.customSelect');
                const text = $item.text();
                const $label = $container.find('.selectLabel');
                const $allOptions = $container.find('.selectOptions li');
                const val = $item.attr('data-value') ?? '';
                const type = $item.attr('data-type') ?? '';
                const geraet = $item.attr('data-geraet') ?? '';

                $allOptions.removeClass('selected');
                $item.addClass('selected');

                $label.text(text).removeClass('placeholder');
                $container.removeClass('open');

                $.ajax({
                    url: '/intern/scripts/ranklive/ajax-get-ranklive-config.php',
                    method: 'POST',
                    data: {
                        csrf_token,
                        slug: val
                    },
                    success: function (response) {
                        if (typeof response === "string") {
                            response = response ? JSON.parse(response) : {};
                        }

                        if (!response.success) {
                            displayMsg(2, response.message || "Unbekannter Fehler");
                            return;
                        }

                        active_type_slug = val;

                        $customSelectColumns.addClass('hidden');

                        if (response.data === "") {
                            $('#headerRowRankLiveConfig').html('');
                            $('#bodyRowRankLiveConfig').html('');
                            $('#addColumn').removeClass('hidden');
                        } else {
                            loadTable(response.data);
                        }

                        configureAddOptionDropdown(type, geraet);
                    },
                    error: function (xhr, status, errorThrown) {
                        displayMsg(0, "Fehler");
                        console.error(xhr);
                    }
                });
            });

            $('#importConfig').on('change', async function () {

                if (!await displayConfirm("Die aktuelle Konfiguration wird durch die ausgewählte Datei vollständig überschrieben!")) return;

                const input = $(this)[0];

                const formData = new FormData();

                formData.append('csrf_token', csrf_token);
                formData.append('configFile', input.files[0]);
                formData.append('slug', active_type_slug);

                $.ajax({
                    url: '/intern/scripts/ranklive/upload-config-file.php',
                    type: 'POST',
                    data: formData,
                    processData: false,
                    contentType: false,
                    success: function (response) {
                        response = response ? JSON.parse(response) : {};
                        if (response.success) {
                            window.location.reload();
                        } else {
                            if (response.message) {
                                displayMsg(0, response.message);
                            } else {
                                displayMsg(0, "Unbekannter Fehler beim Hochladen der Config-Datei.");
                            }
                        }
                    },
                    error: function (xhr, status, errorThrown) {
                        let errorMsg = "Kritischer Fehler beim Hochladen der Config-Datei.";

                        if (xhr.responseText) {
                            try {
                                const response = JSON.parse(xhr.responseText);
                                if (response.message) {
                                    errorMsg = response.message;
                                }
                            } catch (e) {
                                console.error("Could not parse JSON error response:", e);
                            }
                        }

                        displayMsg(0, errorMsg);

                        console.error(xhr);
                    }
                });

            });

            $('#exportConfig').on('click', function () {
                $.ajax({
                    url: '/intern/scripts/ranklive/export-config-file.php',
                    method: 'POST',
                    data: {
                        csrf_token: csrf_token,
                        slug: active_type_slug
                    },
                    dataType: 'text',
                    success: function(response, status, xhr) {
                       
                        const disposition = xhr.getResponseHeader('Content-Disposition');
                        let filename = `${active_type_slug}.wkvstable`;

                        if (disposition && disposition.indexOf('attachment') !== -1) {
                            const filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
                            const matches = filenameRegex.exec(disposition);
                            if (matches != null && matches[1]) { 
                                filename = matches[1].replace(/['"]/g, '');
                            }
                        }

                        const blob = new Blob([response], { type: 'application/json' });
                        
                        const $tempLink = $('<a>', {
                            href: URL.createObjectURL(blob),
                            download: filename
                        });
                        
                        $('body').append($tempLink);
                        $tempLink[0].click();
                        
                        $tempLink.remove();
                        URL.revokeObjectURL($tempLink.attr('href'));

                        displayMsg(1, "Tabelle erfolgreich exportiert.");
                    },
                    error: function(xhr, status, error) {
                        displayMsg(0, "Tabelle konnte nicht exportiert werden.");
                    }
                });
            });
        </script>

    </body>

    </html>
<?php endif; ?>