
export default function (component) {
    const { data, parentElement } = component;

    // Parse TOON (Token Oriented Object Notation) text
    // Preserves the order of keys as they appear in the input
    function parseTOON(text) {
        const lines = text.split('\n');
        const result = {}; // Order is preserved in modern JS (ES2015+)
        let currentArray = null;
        let arrayFields = [];

        // Process lines sequentially to maintain order
        for (let i = 0; i < lines.length; i++) {
            const line = lines[i];

            // Skip empty lines
            if (!line.trim()) {
                currentArray = null;
                continue;
            }

            // Check for object definition with inline values: context{field1,field2}: val1,val2
            const objInlineMatch = line.match(/^([^{]+)\{([^}]+)\}:\s*(.+)$/);
            if (objInlineMatch) {
                const objName = objInlineMatch[1].trim();
                const fields = objInlineMatch[2].split(',').map(f => f.trim());
                const values = objInlineMatch[3].trim().split(',').map(v => v.trim());

                const obj = {};
                fields.forEach((field, idx) => {
                    if (idx < values.length) {
                        obj[field] = parseValue(values[idx]);
                    }
                });
                result[objName] = obj;
                currentArray = null;
                continue;
            }

            // Check for array definition with inline values: friends[3]: val1,val2,val3
            const arrayInlineMatch = line.match(/^([^\[]+)\[(\d+)\]:\s*(.+)$/);
            if (arrayInlineMatch) {
                const arrayName = arrayInlineMatch[1].trim();
                const arraySize = parseInt(arrayInlineMatch[2]);
                const valuesStr = arrayInlineMatch[3].trim();

                // Check if values end with a period
                const values = valuesStr.replace(/\.$/, '').split(',').map(v => v.trim());
                result[arrayName] = values.map(v => parseValue(v));
                currentArray = null;
                continue;
            }

            // Check if this is an array definition with schema: items[2]{id,value}: or items[2]{id,value},
            const arrayMatch = line.match(/^([^,]+)\[(\d+)\]\{([^}]+)\}[:,]?$/);
            if (arrayMatch) {
                const arrayName = arrayMatch[1].trim();
                const arraySize = parseInt(arrayMatch[2]);
                const fields = arrayMatch[3].split(',').map(f => f.trim());

                result[arrayName] = [];
                currentArray = { name: arrayName, fields: fields, data: result[arrayName] };
                arrayFields = fields;
                continue;
            }

            // Check if this is indented array data
            if (line.startsWith('  ') && currentArray) {
                const valueStr = line.trim();
                // Remove trailing period if present
                const cleanStr = valueStr.replace(/\.$/, '');
                const values = cleanStr.split(',').map(v => v.trim());
                const obj = {};
                arrayFields.forEach((field, idx) => {
                    if (idx < values.length) {
                        obj[field] = parseValue(values[idx]);
                    }
                });
                currentArray.data.push(obj);
                continue;
            }

            // Regular key-value pair: name,Example
            const commaIndex = line.indexOf(',');
            if (commaIndex > 0) {
                const key = line.slice(0, commaIndex).trim();
                const valueStr = line.slice(commaIndex + 1).trim();

                if (key && valueStr) {
                    result[key] = parseValue(valueStr);
                }
            }
        }

        return result;
    }

    function parseValue(str) {
        str = str.trim();

        // Empty string
        if (!str) return '';

        // Number
        if (!isNaN(str) && str !== '') {
            return Number(str);
        }

        // Boolean-like
        if (str.toLowerCase() === 'true') return true;
        if (str.toLowerCase() === 'false') return false;
        if (str.toLowerCase() === 'null') return null;

        // String with quotes (remove them)
        if ((str.startsWith('"') && str.endsWith('"')) ||
            (str.startsWith("'") && str.endsWith("'"))) {
            return str.slice(1, -1);
        }

        // Default: return as string
        return str;
    }

    // Check maximum nesting depth
    function checkMaxDepth(obj, maxDepth = 5, currentDepth = 1) {
        if (currentDepth > maxDepth) {
            throw new Error(`TOON data exceeds maximum nesting depth of ${maxDepth} levels`);
        }

        if (typeof obj === 'object' && obj !== null) {
            if (Array.isArray(obj)) {
                for (const item of obj) {
                    checkMaxDepth(item, maxDepth, currentDepth + 1);
                }
            } else {
                for (const value of Object.values(obj)) {
                    checkMaxDepth(value, maxDepth, currentDepth + 1);
                }
            }
        }
    }

    function getValueType(value) {
        if (value === null) return 'null';
        if (Array.isArray(value)) return 'array';
        if (typeof value === 'object') return 'object';
        if (typeof value === 'boolean') return 'boolean';
        if (typeof value === 'number') return 'number';
        if (typeof value === 'string') return 'string';
        return 'unknown';
    }

    function escapeHtml(text) {
        const div = document.createElement('div');
        div.textContent = text;
        return div.innerHTML;
    }


    // Data store for copy functionality
    window.toonDataStore = {};

    // Copy to clipboard function
    window.copyToClipboard = function (button, dataId) {
        const data = window.toonDataStore[dataId];
        if (!data) {
            console.error('Data not found for id:', dataId);
            return;
        }

        // Convert to JSON with proper formatting
        const text = JSON.stringify(data, null, 2);

        navigator.clipboard.writeText(text).then(() => {
            button.classList.add('copied');
            setTimeout(() => {
                button.classList.remove('copied');
            }, 1500);
        }).catch(err => {
            console.error('Failed to copy:', err);
        });
    }

    function createCollapsibleLine(key, value, isLast = false) {
        const id = `section-${Math.random().toString(36).substr(2, 9)}`;
        const dataId = `data-${Math.random().toString(36).substr(2, 9)}`;
        const isObject = typeof value === 'object' && value !== null && !Array.isArray(value);
        const isArray = Array.isArray(value);

        // Store data for copying
        const dataToStore = {};
        dataToStore[key] = value;
        window.toonDataStore[dataId] = dataToStore;

        if (!isObject && !isArray) {
            // Simple key-value pair
            const formattedValue = formatValue(value);
            return `
                <div class="toon-line">
                    <span class="toggle-placeholder"></span>
                    <div class="toon-content-wrapper">
                        <span class="toon-key">"${escapeHtml(key)}"</span>
                        <span class="toon-punctuation">:</span>
                        <span class="toon-value ${getValueType(value)}">${formattedValue}</span>
                    </div>
                    <button class="copy-btn" onclick="copyToClipboard(this, '${dataId}')">
                        <svg viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg">
                            <path d="m30 35h-25v-22.5h25v7.5h2.5v-12.5c0-1.4-1.1-2.5-2.5-2.5h-7.5c0-2.8-2.2-5-5-5s-5 2.2-5 5h-7.5c-1.4 0-2.5 1.1-2.5 2.5v27.5c0 1.4 1.1 2.5 2.5 2.5h25c1.4 0 2.5-1.1 2.5-2.5v-5h-2.5v5z m-20-27.5h2.5s2.5-1.1 2.5-2.5 1.1-2.5 2.5-2.5 2.5 1.1 2.5 2.5 1.3 2.5 2.5 2.5h2.5s2.5 1.1 2.5 2.5h-20c0-1.5 1.1-2.5 2.5-2.5z m-2.5 20h5v-2.5h-5v2.5z m17.5-5v-5l-10 7.5 10 7.5v-5h12.5v-5h-12.5z m-17.5 10h7.5v-2.5h-7.5v2.5z m12.5-17.5h-12.5v2.5h12.5v-2.5z m-7.5 5h-5v2.5h5v-2.5z"/>
                        </svg>
                    </button>
                </div>
            `;
        }

        if (isArray) {
            // Array with items
            let result = `
                <div class="toon-line">
                    <span class="toggle-icon" data-target="${id}">
                        <svg viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg">
                            <path d="M0 5l6 6 6-6z"/>
                        </svg>
                    </span>
                    <div class="toon-content-wrapper">
                        <span class="toon-key">"${escapeHtml(key)}"</span>
                        <span class="toon-punctuation">:</span>
                    </div>
                    <button class="copy-btn" onclick="event.stopPropagation(); copyToClipboard(this, '${dataId}')">
                        <svg viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg">
                            <path d="m30 35h-25v-22.5h25v7.5h2.5v-12.5c0-1.4-1.1-2.5-2.5-2.5h-7.5c0-2.8-2.2-5-5-5s-5 2.2-5 5h-7.5c-1.4 0-2.5 1.1-2.5 2.5v27.5c0 1.4 1.1 2.5 2.5 2.5h25c1.4 0 2.5-1.1 2.5-2.5v-5h-2.5v5z m-20-27.5h2.5s2.5-1.1 2.5-2.5 1.1-2.5 2.5-2.5 2.5 1.1 2.5 2.5 1.3 2.5 2.5 2.5h2.5s2.5 1.1 2.5 2.5h-20c0-1.5 1.1-2.5 2.5-2.5z m-2.5 20h5v-2.5h-5v2.5z m17.5-5v-5l-10 7.5 10 7.5v-5h12.5v-5h-12.5z m-17.5 10h7.5v-2.5h-7.5v2.5z m12.5-17.5h-12.5v2.5h12.5v-2.5z m-7.5 5h-5v2.5h5v-2.5z"/>
                        </svg>
                    </button>
                </div>
                <div class="toon-children" id="${id}">
            `;

            // Render array items in order with indices
            value.forEach((item, index) => {
                const itemDataId = `data-${Math.random().toString(36).substr(2, 9)}`;
                const itemWithKey = {};
                itemWithKey[index] = item;
                window.toonDataStore[itemDataId] = itemWithKey;

                // If item is an object, render it as nested structure
                if (typeof item === 'object' && item !== null && !Array.isArray(item)) {
                    const itemId = `section-${Math.random().toString(36).substr(2, 9)}`;
                    result += `
                        <div class="toon-line">
                            <span class="toggle-icon" data-target="${itemId}">
                                <svg viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg">
                                    <path d="M0 5l6 6 6-6z"/>
                                </svg>
                            </span>
                            <div class="toon-content-wrapper">
                                <span class="toon-index">${index}</span>
                                <span class="toon-punctuation">:</span>
                            </div>
                            <button class="copy-btn" onclick="event.stopPropagation(); copyToClipboard(this, '${itemDataId}')">📋</button>
                        </div>
                        <div class="toon-children" id="${itemId}">
                    `;

                    // Render object properties in order
                    Object.entries(item).forEach(([k, v]) => {
                        const subDataId = `data-${Math.random().toString(36).substr(2, 9)}`;
                        const subData = {};
                        subData[k] = v;
                        window.toonDataStore[subDataId] = subData;
                        const formattedValue = formatValue(v);

                        result += `
                            <div class="toon-line">
                                <span class="toggle-placeholder"></span>
                                <div class="toon-content-wrapper">
                                    <span class="toon-key">"${escapeHtml(k)}"</span>
                                    <span class="toon-punctuation">:</span>
                                    <span class="toon-value ${getValueType(v)}">${formattedValue}</span>
                                </div>
                                <button class="copy-btn" onclick="copyToClipboard(this, '${subDataId}')">
                                    <svg viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg">
                                        <path d="m30 35h-25v-22.5h25v7.5h2.5v-12.5c0-1.4-1.1-2.5-2.5-2.5h-7.5c0-2.8-2.2-5-5-5s-5 2.2-5 5h-7.5c-1.4 0-2.5 1.1-2.5 2.5v27.5c0 1.4 1.1 2.5 2.5 2.5h25c1.4 0 2.5-1.1 2.5-2.5v-5h-2.5v5z m-20-27.5h2.5s2.5-1.1 2.5-2.5 1.1-2.5 2.5-2.5 2.5 1.1 2.5 2.5 1.3 2.5 2.5 2.5h2.5s2.5 1.1 2.5 2.5h-20c0-1.5 1.1-2.5 2.5-2.5z m-2.5 20h5v-2.5h-5v2.5z m17.5-5v-5l-10 7.5 10 7.5v-5h12.5v-5h-12.5z m-17.5 10h7.5v-2.5h-7.5v2.5z m12.5-17.5h-12.5v2.5h12.5v-2.5z m-7.5 5h-5v2.5h5v-2.5z"/>
                                    </svg>
                                </button>
                            </div>
                        `;
                    });

                    result += `
                        </div>
                    `;
                } else {
                    // Simple value
                    const formattedValue = formatValue(item);
                    result += `
                        <div class="toon-line">
                            <span class="toggle-placeholder"></span>
                            <div class="toon-content-wrapper">
                                <span class="toon-index">${index}</span>
                                <span class="toon-punctuation">:</span>
                                <span class="toon-value ${getValueType(item)}">${formattedValue}</span>
                            </div>
                            <button class="copy-btn" onclick="copyToClipboard(this, '${itemDataId}')">
                                <svg viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg">
                                    <path d="m30 35h-25v-22.5h25v7.5h2.5v-12.5c0-1.4-1.1-2.5-2.5-2.5h-7.5c0-2.8-2.2-5-5-5s-5 2.2-5 5h-7.5c-1.4 0-2.5 1.1-2.5 2.5v27.5c0 1.4 1.1 2.5 2.5 2.5h25c1.4 0 2.5-1.1 2.5-2.5v-5h-2.5v5z m-20-27.5h2.5s2.5-1.1 2.5-2.5 1.1-2.5 2.5-2.5 2.5 1.1 2.5 2.5 1.3 2.5 2.5 2.5h2.5s2.5 1.1 2.5 2.5h-20c0-1.5 1.1-2.5 2.5-2.5z m-2.5 20h5v-2.5h-5v2.5z m17.5-5v-5l-10 7.5 10 7.5v-5h12.5v-5h-12.5z m-17.5 10h7.5v-2.5h-7.5v2.5z m12.5-17.5h-12.5v2.5h12.5v-2.5z m-7.5 5h-5v2.5h5v-2.5z"/>
                                </svg>
                            </button>
                        </div>
                    `;
                }
            });

            result += `
                </div>
            `;

            return result;
        }

        // Object/nested structure (order preserved)
        const entries = Object.entries(value);
        let result = `
            <div class="toon-line">
                <span class="toggle-icon" data-target="${id}">
                    <svg viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg">
                        <path d="M0 5l6 6 6-6z"/>
                    </svg>
                </span>
                <div class="toon-content-wrapper">
                    <span class="toon-key">"${escapeHtml(key)}"</span>
                    <span class="toon-punctuation">:</span>
                </div>
                <button class="copy-btn" onclick="event.stopPropagation(); copyToClipboard(this, '${dataId}')">📋</button>
            </div>
            <div class="toon-children" id="${id}">
        `;

        entries.forEach(([k, v], idx) => {
            result += createCollapsibleLine(k, v, idx === entries.length - 1);
        });

        result += `
            </div>
        `;

        return result;
    }

    function formatValue(value) {
        const type = getValueType(value);
        if (type === 'string') {
            return `"${escapeHtml(value)}"`;
        }
        if (type === 'null') {
            return 'null';
        }
        return escapeHtml(String(value));
    }


    function renderTOON(toonData) {
        const container = parentElement.querySelector('#toon-container');

        try {
            // Clear previous data store
            window.toonDataStore = {};

            const parsed = typeof toonData === 'string' ? parseTOON(toonData) : toonData;

            // Validate maximum nesting depth (5 levels)
            checkMaxDepth(parsed, 5);

            // Store entire data for root copy button
            const rootDataId = 'data-root';
            window.toonDataStore[rootDataId] = parsed;

            // Render top-level object with copy button in top-right
            let html = `
                <button class="copy-btn root-copy-btn" onclick="copyToClipboard(this, '${rootDataId}')">
                    <svg viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg">
                        <path d="m30 35h-25v-22.5h25v7.5h2.5v-12.5c0-1.4-1.1-2.5-2.5-2.5h-7.5c0-2.8-2.2-5-5-5s-5 2.2-5 5h-7.5c-1.4 0-2.5 1.1-2.5 2.5v27.5c0 1.4 1.1 2.5 2.5 2.5h25c1.4 0 2.5-1.1 2.5-2.5v-5h-2.5v5z m-20-27.5h2.5s2.5-1.1 2.5-2.5 1.1-2.5 2.5-2.5 2.5 1.1 2.5 2.5 1.3 2.5 2.5 2.5h2.5s2.5 1.1 2.5 2.5h-20c0-1.5 1.1-2.5 2.5-2.5z m-2.5 20h5v-2.5h-5v2.5z m17.5-5v-5l-10 7.5 10 7.5v-5h12.5v-5h-12.5z m-17.5 10h7.5v-2.5h-7.5v2.5z m12.5-17.5h-12.5v2.5h12.5v-2.5z m-7.5 5h-5v2.5h5v-2.5z"/>
                    </svg>
                </button>
                <div class="root-content">
            `;
            // Object.entries preserves insertion order (ES2015+)
            const entries = Object.entries(parsed);
            entries.forEach(([key, value], idx) => {
                html += createCollapsibleLine(key, value, idx === entries.length - 1);
            });
            html += `
                </div>
            `;

            container.innerHTML = html;

            // Add click handlers for toggle icons
            parentElement.querySelectorAll('.toggle-icon').forEach(icon => {
                icon.addEventListener('click', function () {
                    const targetId = this.getAttribute('data-target');
                    const content = parentElement.querySelector('#' + targetId);

                    if (content.classList.contains('collapsed')) {
                        content.classList.remove('collapsed');
                        this.classList.remove('collapsed');
                    } else {
                        content.classList.add('collapsed');
                        this.classList.add('collapsed');
                    }
                });
            });

        } catch (error) {
            container.innerHTML = `
                <div style="color: #D84315; padding: 10px; background: rgba(216, 67, 21, 0.1); border-radius: 4px; border-left: 4px solid #D84315;">
                    <strong>Error parsing TOON data:</strong><br>
                    ${escapeHtml(error.message)}
                </div>
            `;
        }
    }

    // Get TOON data from component
    const toonData = data || '';

    // Initial render with data from Streamlit
    if (toonData && toonData.length > 0) {
        renderTOON(toonData);
    } else {
        const container = parentElement.querySelector('#toon-container');
        container.innerHTML = '<div style="color: #6c757d; padding: 20px; text-align: center; font-style: italic;">No TOON data provided</div>';
    }
}