// modules/canvas-animations/DataVisualization.js
import { CanvasManager } from './CanvasManager.js';
import { Logger } from '../../core/logger.js';

/**
 * Data Visualization Canvas Components - Animated charts and graphs
 */
export const DataVisualization = {
    
    /**
     * Initialize data visualization canvas
     */
    init(canvas, config) {
        const manager = new CanvasManager(canvas);
        const vizType = config.type || 'bar';
        
        // Get data from config or data attributes
        const data = this.parseData(canvas, config);
        
        if (!data || data.length === 0) {
            Logger.warn('[DataVisualization] No data provided for canvas');
            return;
        }
        
        switch (vizType) {
            case 'bar':
                this.createBarChart(manager, data, config);
                break;
            case 'line':
                this.createLineChart(manager, data, config);
                break;
            case 'pie':
                this.createPieChart(manager, data, config);
                break;
            case 'progress':
                this.createProgressChart(manager, data, config);
                break;
            default:
                this.createBarChart(manager, data, config);
        }
        
        Logger.info('[DataVisualization] Initialized', vizType, 'chart with', data.length, 'data points');
    },
    
    /**
     * Parse data from canvas element or config
     */
    parseData(canvas, config) {
        let data = config.data;
        
        // Try to get data from data-canvas-data attribute
        if (!data && canvas.dataset.canvasData) {
            try {
                data = JSON.parse(canvas.dataset.canvasData);
            } catch (e) {
                Logger.warn('[DataVisualization] Failed to parse canvas data', e);
            }
        }
        
        // Try to get data from script tag
        if (!data) {
            const scriptTag = canvas.nextElementSibling;
            if (scriptTag && scriptTag.tagName === 'SCRIPT' && scriptTag.type === 'application/json') {
                try {
                    data = JSON.parse(scriptTag.textContent);
                } catch (e) {
                    Logger.warn('[DataVisualization] Failed to parse script data', e);
                }
            }
        }
        
        // Ensure data is always an array
        if (!data) {
            Logger.warn('[DataVisualization] No data found');
            return [];
        }
        
        // If data is not an array, wrap it or convert it
        if (!Array.isArray(data)) {
            // If it's a single number (for progress charts)
            if (typeof data === 'number') {
                data = [{ value: data, label: 'Progress' }];
            }
            // If it's an object with values, convert to array
            else if (typeof data === 'object') {
                data = Object.entries(data).map(([key, value]) => ({
                    label: key,
                    value: typeof value === 'object' ? value.value || value : value
                }));
            }
            // Fallback: empty array
            else {
                Logger.warn('[DataVisualization] Data format not recognized:', data);
                return [];
            }
        }
        
        return data;
    },
    
    /**
     * Create animated bar chart
     */
    createBarChart(manager, data, config) {
        const { ctx } = manager;
        const { width, height } = manager.getSize();
        
        const padding = config.padding || 40;
        const chartWidth = width - padding * 2;
        const chartHeight = height - padding * 2;
        
        const barWidth = chartWidth / data.length * 0.8;
        const barSpacing = chartWidth / data.length * 0.2;
        const maxValue = Math.max(...data.map(d => d.value));
        
        let animationProgress = 0;
        const animationDuration = config.animationDuration || 2000;
        let startTime = null;
        
        const animate = (timestamp) => {
            if (!startTime) startTime = timestamp;
            const elapsed = timestamp - startTime;
            
            animationProgress = Math.min(elapsed / animationDuration, 1);
            
            // Easing function (easeOutCubic)
            const progress = 1 - Math.pow(1 - animationProgress, 3);
            
            manager.clear();
            this.renderBarChart(manager, data, config, progress, {
                padding,
                chartWidth,
                chartHeight,
                barWidth,
                barSpacing,
                maxValue
            });
            
            if (animationProgress < 1) {
                requestAnimationFrame(animate);
            }
        };
        
        requestAnimationFrame(animate);
    },
    
    /**
     * Render bar chart frame
     */
    renderBarChart(manager, data, config, progress, layout) {
        const { ctx } = manager;
        const { padding, chartHeight, barWidth, barSpacing, maxValue } = layout;
        
        // Draw bars
        data.forEach((item, index) => {
            const x = padding + index * (barWidth + barSpacing);
            const barHeight = (item.value / maxValue) * chartHeight * progress;
            const y = padding + chartHeight - barHeight;
            
            // Bar
            ctx.fillStyle = item.color || config.barColor || 'rgba(100, 150, 255, 0.8)';
            ctx.fillRect(x, y, barWidth, barHeight);
            
            // Label
            if (config.showLabels !== false) {
                ctx.fillStyle = config.textColor || '#333';
                ctx.font = config.font || '12px Arial';
                ctx.textAlign = 'center';
                ctx.fillText(
                    item.label, 
                    x + barWidth / 2, 
                    padding + chartHeight + 20
                );
                
                // Value
                if (config.showValues !== false) {
                    ctx.fillText(
                        Math.round(item.value * progress), 
                        x + barWidth / 2, 
                        y - 5
                    );
                }
            }
        });
        
        // Draw axes if enabled
        if (config.showAxes !== false) {
            ctx.strokeStyle = config.axisColor || '#ccc';
            ctx.lineWidth = 1;
            
            // Y-axis
            ctx.beginPath();
            ctx.moveTo(padding, padding);
            ctx.lineTo(padding, padding + chartHeight);
            ctx.stroke();
            
            // X-axis
            ctx.beginPath();
            ctx.moveTo(padding, padding + chartHeight);
            ctx.lineTo(padding + layout.chartWidth, padding + chartHeight);
            ctx.stroke();
        }
    },
    
    /**
     * Create animated line chart
     */
    createLineChart(manager, data, config) {
        const { ctx } = manager;
        const { width, height } = manager.getSize();
        
        const padding = config.padding || 40;
        const chartWidth = width - padding * 2;
        const chartHeight = height - padding * 2;
        
        const maxValue = Math.max(...data.map(d => d.value));
        const minValue = Math.min(...data.map(d => d.value));
        const valueRange = maxValue - minValue;
        
        let animationProgress = 0;
        const animationDuration = config.animationDuration || 2000;
        let startTime = null;
        
        const animate = (timestamp) => {
            if (!startTime) startTime = timestamp;
            const elapsed = timestamp - startTime;
            
            animationProgress = Math.min(elapsed / animationDuration, 1);
            
            manager.clear();
            this.renderLineChart(manager, data, config, animationProgress, {
                padding,
                chartWidth,
                chartHeight,
                maxValue,
                minValue,
                valueRange
            });
            
            if (animationProgress < 1) {
                requestAnimationFrame(animate);
            }
        };
        
        requestAnimationFrame(animate);
    },
    
    /**
     * Render line chart frame
     */
    renderLineChart(manager, data, config, progress, layout) {
        const { ctx } = manager;
        const { padding, chartWidth, chartHeight, minValue, valueRange } = layout;
        
        const pointsToShow = Math.floor(data.length * progress);
        
        ctx.strokeStyle = config.lineColor || 'rgba(100, 150, 255, 0.8)';
        ctx.lineWidth = config.lineWidth || 3;
        ctx.lineCap = 'round';
        ctx.lineJoin = 'round';
        
        // Draw line
        ctx.beginPath();
        for (let i = 0; i <= pointsToShow && i < data.length; i++) {
            const x = padding + (i / (data.length - 1)) * chartWidth;
            const y = padding + chartHeight - ((data[i].value - minValue) / valueRange) * chartHeight;
            
            if (i === 0) {
                ctx.moveTo(x, y);
            } else {
                ctx.lineTo(x, y);
            }
        }
        ctx.stroke();
        
        // Draw points
        if (config.showPoints !== false) {
            ctx.fillStyle = config.pointColor || config.lineColor || 'rgba(100, 150, 255, 0.8)';
            
            for (let i = 0; i <= pointsToShow && i < data.length; i++) {
                const x = padding + (i / (data.length - 1)) * chartWidth;
                const y = padding + chartHeight - ((data[i].value - minValue) / valueRange) * chartHeight;
                
                ctx.beginPath();
                ctx.arc(x, y, config.pointSize || 4, 0, Math.PI * 2);
                ctx.fill();
                
                // Labels
                if (config.showLabels !== false && data[i].label) {
                    ctx.fillStyle = config.textColor || '#333';
                    ctx.font = config.font || '12px Arial';
                    ctx.textAlign = 'center';
                    ctx.fillText(data[i].label, x, padding + chartHeight + 20);
                }
            }
        }
    },
    
    /**
     * Create animated pie chart
     */
    createPieChart(manager, data, config) {
        const { ctx } = manager;
        const { width, height } = manager.getSize();
        
        const centerX = width / 2;
        const centerY = height / 2;
        const radius = Math.min(width, height) / 2 * 0.8;
        
        const total = data.reduce((sum, item) => sum + item.value, 0);
        
        let animationProgress = 0;
        const animationDuration = config.animationDuration || 2000;
        let startTime = null;
        
        const animate = (timestamp) => {
            if (!startTime) startTime = timestamp;
            const elapsed = timestamp - startTime;
            
            animationProgress = Math.min(elapsed / animationDuration, 1);
            
            manager.clear();
            this.renderPieChart(manager, data, config, animationProgress, {
                centerX,
                centerY,
                radius,
                total
            });
            
            if (animationProgress < 1) {
                requestAnimationFrame(animate);
            }
        };
        
        requestAnimationFrame(animate);
    },
    
    /**
     * Render pie chart frame
     */
    renderPieChart(manager, data, config, progress, layout) {
        const { ctx } = manager;
        const { centerX, centerY, radius, total } = layout;
        
        let currentAngle = -Math.PI / 2; // Start at top
        const maxAngle = currentAngle + (Math.PI * 2 * progress);
        
        for (let index = 0; index < data.length; index++) {
            if (currentAngle >= maxAngle) break;
            
            const item = data[index];
            const sliceAngle = (item.value / total) * Math.PI * 2;
            const endAngle = Math.min(currentAngle + sliceAngle, maxAngle);
            
            if (endAngle > currentAngle) {
                // Draw slice
                ctx.fillStyle = item.color || this.getDefaultColor(index);
                ctx.beginPath();
                ctx.moveTo(centerX, centerY);
                ctx.arc(centerX, centerY, radius, currentAngle, endAngle);
                ctx.closePath();
                ctx.fill();
                
                // Draw labels if enabled
                if (config.showLabels !== false && endAngle === currentAngle + sliceAngle) {
                    const labelAngle = currentAngle + sliceAngle / 2;
                    const labelX = centerX + Math.cos(labelAngle) * radius * 0.7;
                    const labelY = centerY + Math.sin(labelAngle) * radius * 0.7;
                    
                    ctx.fillStyle = config.textColor || '#333';
                    ctx.font = config.font || '12px Arial';
                    ctx.textAlign = 'center';
                    ctx.fillText(item.label, labelX, labelY);
                }
            }
            
            currentAngle += sliceAngle;
        }
    },
    
    /**
     * Create progress visualization
     */
    createProgressChart(manager, data, config) {
        const { ctx } = manager;
        const { width, height } = manager.getSize();
        
        let animationProgress = 0;
        const animationDuration = config.animationDuration || 1500;
        let startTime = null;
        
        const animate = (timestamp) => {
            if (!startTime) startTime = timestamp;
            const elapsed = timestamp - startTime;
            
            animationProgress = Math.min(elapsed / animationDuration, 1);
            
            manager.clear();
            this.renderProgressChart(manager, data, config, animationProgress);
            
            if (animationProgress < 1) {
                requestAnimationFrame(animate);
            }
        };
        
        requestAnimationFrame(animate);
    },
    
    /**
     * Render progress chart
     */
    renderProgressChart(manager, data, config, progress) {
        const { ctx } = manager;
        const { width, height } = manager.getSize();
        
        const centerX = width / 2;
        const centerY = height / 2;
        const radius = Math.min(width, height) / 2 * 0.8;
        const lineWidth = config.lineWidth || 20;
        
        // Get progress value from data array
        const value = data[0]?.value || 0;
        const maxValue = config.maxValue || 100;
        const progressValue = (value / maxValue) * progress;
        
        // Background circle
        ctx.strokeStyle = config.backgroundColor || 'rgba(200, 200, 200, 0.3)';
        ctx.lineWidth = lineWidth;
        ctx.beginPath();
        ctx.arc(centerX, centerY, radius, 0, Math.PI * 2);
        ctx.stroke();
        
        // Progress arc
        ctx.strokeStyle = config.color || 'rgba(100, 150, 255, 0.8)';
        ctx.lineCap = 'round';
        ctx.beginPath();
        ctx.arc(centerX, centerY, radius, -Math.PI / 2, -Math.PI / 2 + (progressValue / maxValue) * Math.PI * 2);
        ctx.stroke();
        
        // Center text
        if (config.showText !== false) {
            ctx.fillStyle = config.textColor || '#333';
            ctx.font = config.font || 'bold 24px Arial';
            ctx.textAlign = 'center';
            ctx.textBaseline = 'middle';
            ctx.fillText(Math.round(progressValue) + '%', centerX, centerY);
        }
    },
    
    /**
     * Get default color for data point
     */
    getDefaultColor(index) {
        const colors = [
            'rgba(100, 150, 255, 0.8)',
            'rgba(255, 100, 150, 0.8)',
            'rgba(150, 255, 100, 0.8)',
            'rgba(255, 200, 100, 0.8)',
            'rgba(200, 100, 255, 0.8)',
            'rgba(100, 255, 200, 0.8)'
        ];
        return colors[index % colors.length];
    }
};