/* PrismJS - Minimal Core for GitHub Code Viewer */
/* This is a simplified version focused on safety and basic highlighting */

(function(){

if (typeof self === 'undefined' || !self.Prism || !self.document) {
    return;
}

var Prism = window.Prism = {
    languages: {},
    
    // Simplified tokenization with infinite loop prevention
    tokenize: function(text, grammar) {
        // Prevent tokenizing huge files
        if (text.length > 100000) {
            return [text]; // Return as plain text for very large files
        }
        
        var tokens = [];
        var rest = text;
        var maxIterations = 10000; // Prevent infinite loops
        var iterations = 0;
        
        while (rest.length > 0 && iterations < maxIterations) {
            iterations++;
            var matchFound = false;
            
            for (var token in grammar) {
                if (!grammar.hasOwnProperty(token) || !grammar[token]) {
                    continue;
                }
                
                var pattern = grammar[token];
                if (pattern instanceof RegExp) {
                    var matches = rest.match(pattern);
                    
                    if (matches && matches.index === 0) {
                        matchFound = true;
                        tokens.push({
                            type: token,
                            content: matches[0]
                        });
                        rest = rest.substring(matches[0].length);
                        break;
                    }
                }
            }
            
            // If no match found, consume one character as plain text
            if (!matchFound) {
                if (tokens.length > 0 && typeof tokens[tokens.length - 1] === 'string') {
                    tokens[tokens.length - 1] += rest.charAt(0);
                } else {
                    tokens.push(rest.charAt(0));
                }
                rest = rest.substring(1);
            }
        }
        
        // Add any remaining text
        if (rest.length > 0) {
            tokens.push(rest);
        }
        
        return tokens;
    },
    
    // Highlight element
    highlightElement: function(element) {
        var language = element.className.match(/language-(\w+)/);
        if (!language) return;
        
        language = language[1];
        var grammar = Prism.languages[language];
        
        if (!grammar) return;
        
        // Get text content (already HTML escaped by PHP)
        var code = element.textContent;
        
        // Simple tokenization
        var tokens = Prism.tokenize(code, grammar);
        
        // Build highlighted HTML (safe because content is already escaped)
        var highlighted = tokens.map(function(token) {
            if (typeof token === 'string') {
                return token;
            }
            return '<span class="token ' + token.type + '">' + token.content + '</span>';
        }).join('');
        
        element.innerHTML = highlighted;
    },
    
    // Highlight all code blocks
    highlightAll: function() {
        var elements = document.querySelectorAll('code[class*="language-"], [class*="language-"] code');
        for (var i = 0, element; element = elements[i++];) {
            Prism.highlightElement(element);
        }
    }
};

// Define basic grammars for common languages
Prism.languages.javascript = {
    'comment': /\/\/.*|\/\*[\s\S]*?\*\//,
    'string': /(["'])(?:\\.|(?!\1)[^\\\r\n])*\1/,
    'keyword': /\b(?:var|let|const|function|return|if|else|for|while|do|switch|case|break|continue|typeof|instanceof|new|this|throw|try|catch|finally|async|await|class|extends|super|import|export|default|yield)\b/,
    'boolean': /\b(?:true|false)\b/,
    'number': /\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?/i,
    'function': /[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*(?=\s*\()/,
    'operator': /[+\-*/%=!<>&|^~?:]+/,
    'punctuation': /[{}[\];(),.:]/
};

Prism.languages.python = {
    'comment': /#.*/,
    'string': /(["'])(?:\\.|(?!\1)[^\\\r\n])*\1/,
    'keyword': /\b(?:and|as|assert|async|await|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|not|or|pass|print|raise|return|try|while|with|yield)\b/,
    'boolean': /\b(?:True|False|None)\b/,
    'number': /\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?j?/i,
    'operator': /[+\-*/%=!<>&|^~]+/,
    'punctuation': /[{}[\];(),.:]/
};

Prism.languages.php = {
    'comment': /\/\/.*|\/\*[\s\S]*?\*\/|#.*/,
    'string': /(["'])(?:\\.|(?!\1)[^\\\r\n])*\1/,
    'keyword': /\b(?:abstract|and|array|as|break|callable|case|catch|class|clone|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|eval|exit|extends|final|finally|for|foreach|function|global|goto|if|implements|include|include_once|instanceof|insteadof|interface|isset|list|namespace|new|or|print|private|protected|public|require|require_once|return|static|switch|throw|trait|try|unset|use|var|while|xor|yield)\b/i,
    'boolean': /\b(?:false|true)\b/i,
    'variable': /\$\w+/,
    'number': /\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?/i,
    'operator': /[+\-*/%=!<>&|^~?:]+/,
    'punctuation': /[{}[\];(),.:]/
};

Prism.languages.html = Prism.languages.xml = {
    'comment': /<!--[\s\S]*?-->/,
    'tag': {
        pattern: /<\/?[^\s>\/]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\.|(?!\1)[^\\])*\1|[^\s'">=]+))?)*\s*\/?>/i,
        inside: {
            'punctuation': /^<\/?|\/?>$/,
            'attr-name': /[^\s>\/]+/,
            'attr-value': /=(?:("|')(?:\\.|(?!\1)[^\\])*\1|[^\s'">=]+)/i
        }
    }
};

Prism.languages.css = {
    'comment': /\/\*[\s\S]*?\*\//,
    'atrule': /@[\w-]+?.*?(?:;|(?=\s*\{))/i,
    'url': /url\((?:(["'])(?:\\.|(?!\1)[^\\\r\n])*\1|.*?)\)/i,
    'selector': /[^{}\s][^{}]*(?=\s*\{)/,
    'string': /(["'])(?:\\.|(?!\1)[^\\\r\n])*\1/,
    'property': /[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i,
    'important': /!important\b/i,
    'punctuation': /[(){};:]/
};

Prism.languages.json = {
    'property': /"(?:\\.|[^\\"\r\n])*"(?=\s*:)/i,
    'string': /"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,
    'number': /\b0x[\dA-Fa-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:[Ee][+-]?\d+)?/,
    'punctuation': /[{}[\]);,]/,
    'operator': /:/g,
    'boolean': /\b(?:true|false)\b/i,
    'null': /\bnull\b/i
};

// Language aliases
Prism.languages.js = Prism.languages.javascript;
Prism.languages.py = Prism.languages.python;

// Auto-initialize
if (document.readyState !== 'loading') {
    setTimeout(Prism.highlightAll, 0);
} else {
    document.addEventListener('DOMContentLoaded', Prism.highlightAll);
}

})();
