/**
 * Client-side compiler that parses PHP code and simulates functions
 * for accurate preview rendering
 */
class Compiler {
    constructor() {
        this.canvas = null;
        this.fontManager = window.fontManager;
    }
    
    setCanvas(canvas) {
        this.canvas = canvas;
    }
    
    /**
     * Parse PHP code and execute drawing functions
     * @param {string} code - PHP code to parse
     */
    async parseCode(code) {
        if (!this.canvas) {
            console.error('Canvas not set for compiler');
            return;
        }
        
        // Clear the canvas first
        this.canvas.clear();
        
        // Parse lines one by one
        const lines = code.split('\n');
        
        // Process each line
        for (let i = 0; i < lines.length; i++) {
            let line = lines[i].trim();
            
            // Skip empty lines and comments
            if (line === '' || line.startsWith('//') || line.startsWith('#') || line.match(/^\s*\/\*/)) {
                continue;
            }
            
            // Skip PHP opening and closing tags
            if (line.includes('<?php') || line.includes('?>')) {
                continue;
            }
            
            // Check for drawText function
            if (line.includes('drawText(')) {
                await this.processDrawText(line);
            }
            
            // Check for getData function (for simulation)
            if (line.includes('getData(')) {
                this.processGetData(line);
            }
            
            // Check for setPixel function
            if (line.includes('setPixel(')) {
                this.processSetPixel(line);
            }
        }
    }
    
    /**
     * Process drawText function calls
     * @param {string} line - PHP code line containing drawText call
     */
    async processDrawText(line) {
        try {
            // Extract parameters from the function call
            const params = this.extractFunctionParams(line, 'drawText');
            
            if (params.length >= 3) {
                // Parse parameters
                const x = parseInt(params[0]);
                const y = parseInt(params[1]);
                let text = params[2];
                let color = params.length > 3 ? params[3] : '#FFFFFF';
                let font = params.length > 4 ? params[4] : 'bitmap_5x7';
                let justification = params.length > 5 ? params[5] : 'left';
                
                // Clean up string parameters
                text = this.cleanStringParam(text);
                color = this.cleanStringParam(color);
                font = this.cleanStringParam(font);
                justification = this.cleanStringParam(justification);
                
                // Ensure proper font format
                if (!font.startsWith('bitmap_')) {
                    font = 'bitmap_' + font;
                }
                
                // Call the canvas drawText method
                await this.canvas.drawText(x, y, text, color, font, justification);
            }
        } catch (error) {
            console.error('Error processing drawText:', error);
        }
    }
    
    /**
     * Process setPixel function calls
     * @param {string} line - PHP code line containing setPixel call
     */
    processSetPixel(line) {
        try {
            // Extract parameters from the function call
            const params = this.extractFunctionParams(line, 'setPixel');
            
            if (params.length >= 3) {
                // Parse parameters
                const x = parseInt(params[0]);
                const y = parseInt(params[1]);
                let color = params[2];
                
                // Clean up string parameters
                color = this.cleanStringParam(color);
                
                // Call the canvas setPixel method
                this.canvas.setPixel(x, y, color);
            }
        } catch (error) {
            console.error('Error processing setPixel:', error);
        }
    }
    
    /**
     * Simulate getData function for preview
     * @param {string} line - PHP code line containing getData call
     * @returns {string} - Simulated data
     */
    processGetData(line) {
        // For preview, just simulate the data
        // Later, this could be enhanced to perform actual API calls if needed
        const simulatedData = "Sample API Data";
        
        console.log('Simulated getData:', simulatedData);
        return JSON.stringify({
            success: true,
            data: {
                value: Math.floor(Math.random() * 100),
                timestamp: Date.now()
            }
        });
    }
    
    /**
     * Extract function parameters from PHP code
     * @param {string} line - Line of PHP code
     * @param {string} funcName - Function name to extract params for
     * @returns {string[]} - Array of parameter strings
     */
    extractFunctionParams(line, funcName) {
        // Find the function call
        const startPos = line.indexOf(funcName + '(');
        if (startPos === -1) return [];
        
        // Extract the content between parentheses
        const start = startPos + funcName.length + 1;
        let end = start;
        let depth = 1; // Track nested parentheses
        
        // Find the closing parenthesis for this function call
        while (end < line.length && depth > 0) {
            const char = line[end];
            if (char === '(') depth++;
            if (char === ')') depth--;
            if (depth === 0) break;
            end++;
        }
        
        if (end >= line.length) return []; // No closing parenthesis found
        
        // Extract the parameters string
        const paramsStr = line.substring(start, end);
        
        // Parse the parameters, respecting quotes and nested structures
        return this.parseParameters(paramsStr);
    }
    
    /**
     * Parse function parameters respecting quotes and nested structures
     * @param {string} paramsStr - Parameter string
     * @returns {string[]} - Array of individual parameters
     */
    parseParameters(paramsStr) {
        const params = [];
        let current = '';
        let inString = false;
        let stringChar = '';
        let depth = 0; // For nested parentheses or brackets
        
        for (let i = 0; i < paramsStr.length; i++) {
            const char = paramsStr[i];
            
            // Handle string boundaries
            if ((char === '"' || char === "'") && (i === 0 || paramsStr[i-1] !== '\\')) {
                if (!inString) {
                    inString = true;
                    stringChar = char;
                } else if (char === stringChar) {
                    inString = false;
                }
                current += char;
                continue;
            }
            
            // Handle nested structures
            if (char === '(' || char === '[' || char === '{') {
                depth++;
            } else if (char === ')' || char === ']' || char === '}') {
                depth--;
            }
            
            // Parameter separator
            if (char === ',' && !inString && depth === 0) {
                params.push(current.trim());
                current = '';
                continue;
            }
            
            current += char;
        }
        
        // Add the last parameter
        if (current.trim()) {
            params.push(current.trim());
        }
        
        return params;
    }
    
    /**
     * Clean up a string parameter (remove quotes)
     * @param {string} param - Parameter to clean
     * @returns {string} - Cleaned parameter
     */
    cleanStringParam(param) {
        if (typeof param !== 'string') return param;
        
        // Remove quotes around string parameters
        if ((param.startsWith('"') && param.endsWith('"')) || 
            (param.startsWith("'") && param.endsWith("'"))) {
            return param.substring(1, param.length - 1);
        }
        
        return param;
    }
}

// Initialize the compiler
window.compiler = new Compiler();