// Canvas renderer for Kafaball v2
// Draws stadium, players with kick ring, ball, and HUD

class Renderer {
    constructor(canvas) {
        this.canvas = canvas;
        this.ctx = canvas.getContext('2d');
        this.currentState = null;
        this.prevState = null;
        this.stateTimestamp = 0;
        this.prevTimestamp = 0;
        this.animationId = null;

        // State buffer for smoother interpolation
        this.stateBuffer = [];
        this.INTERP_DELAY = 50; // ms behind real-time for smooth interpolation

        // Camera
        this.cameraX = 0;
        this.cameraY = 0;
        this.cameraZoom = 1;
        this.targetCameraX = 0;
        this.targetCameraY = 0;

        // Stadium constants
        this.fieldWidth = 370;
        this.fieldHeight = 170;
        this.goalWidth = 30;
        this.goalPostY = 64;
        this.kickOffRadius = 75;
        this.borderX = 370;
        this.borderY = 170;

        // Colors
        this.colors = {
            grass: '#3d8c40',
            grassDark: '#358038',
            fieldLineBright: 'rgba(255, 255, 255, 0.55)',
            goalRed: 'rgba(229, 110, 86, 0.3)',
            goalBlue: 'rgba(86, 137, 229, 0.3)',
            goalNetRed: '#e56e56',
            goalNetBlue: '#5689e5',
            wall: '#c7e6bd',
            background: '#718c5a'
        };

        this.resize();
        window.addEventListener('resize', () => this.resize());
    }

    resize() {
        this.canvas.width = window.innerWidth;
        this.canvas.height = window.innerHeight;
    }

    updateState(state) {
        this.stateBuffer.push({
            state,
            timestamp: performance.now()
        });
        // Keep only last 10 states
        while (this.stateBuffer.length > 10) {
            this.stateBuffer.shift();
        }
    }

    getInterpolatedState() {
        if (this.stateBuffer.length < 2) {
            return this.stateBuffer.length > 0 ? { state: this.stateBuffer[this.stateBuffer.length - 1].state, alpha: 1 } : null;
        }

        const renderTime = performance.now() - this.INTERP_DELAY;

        // Find the two states to interpolate between
        let prev = this.stateBuffer[0];
        let next = this.stateBuffer[1];

        for (let i = 1; i < this.stateBuffer.length; i++) {
            if (this.stateBuffer[i].timestamp >= renderTime) {
                next = this.stateBuffer[i];
                prev = this.stateBuffer[i - 1];
                break;
            }
            prev = this.stateBuffer[i];
            next = this.stateBuffer[Math.min(i + 1, this.stateBuffer.length - 1)];
        }

        const duration = next.timestamp - prev.timestamp;
        let alpha = duration > 0 ? (renderTime - prev.timestamp) / duration : 1;
        alpha = Math.max(0, Math.min(1, alpha));

        return { prevState: prev.state, nextState: next.state, alpha };
    }

    start() {
        if (this.animationId) return;
        const loop = () => {
            this.render();
            this.animationId = requestAnimationFrame(loop);
        };
        loop();
    }

    stop() {
        if (this.animationId) {
            cancelAnimationFrame(this.animationId);
            this.animationId = null;
        }
    }

    render() {
        const ctx = this.ctx;
        const w = this.canvas.width;
        const h = this.canvas.height;
        ctx.clearRect(0, 0, w, h);

        const interpData = this.getInterpolatedState();
        if (!interpData) {
            ctx.fillStyle = '#1a472a';
            ctx.fillRect(0, 0, w, h);
            return;
        }

        const state = interpData.nextState || interpData.state;
        const prevState = interpData.prevState || null;
        const alpha = interpData.alpha !== undefined ? interpData.alpha : 1;

        if (!state) return;

        // Camera target (follow ball)
        const ball = state.discs.find(d => d.isBall);
        if (ball) {
            this.targetCameraX = ball.x;
            this.targetCameraY = ball.y;
        }

        // Smooth camera
        this.cameraX += (this.targetCameraX - this.cameraX) * 0.08;
        this.cameraY += (this.targetCameraY - this.cameraY) * 0.08;

        // Zoom to fit
        const fieldPixelWidth = (this.borderX * 2 + 100);
        const fieldPixelHeight = (this.borderY * 2 + 100);
        this.cameraZoom = Math.min(w / fieldPixelWidth, h / fieldPixelHeight);

        ctx.save();
        ctx.translate(w / 2, h / 2);
        ctx.scale(this.cameraZoom, this.cameraZoom);
        ctx.translate(-this.cameraX, -this.cameraY);

        this.drawBackground(ctx);
        this.drawField(ctx);
        this.drawSegments(ctx);
        this.drawGoalPosts(ctx);
        this.drawDiscs(ctx, state, prevState, alpha);

        ctx.restore();
    }

    drawBackground(ctx) {
        ctx.fillStyle = this.colors.background;
        ctx.fillRect(-600, -400, 1200, 800);
        ctx.fillStyle = this.colors.grass;
        ctx.fillRect(-this.fieldWidth, -this.fieldHeight, this.fieldWidth * 2, this.fieldHeight * 2);
        const stripeWidth = 37;
        ctx.fillStyle = this.colors.grassDark;
        for (let x = -this.fieldWidth; x < this.fieldWidth; x += stripeWidth * 2) {
            ctx.fillRect(x, -this.fieldHeight, stripeWidth, this.fieldHeight * 2);
        }
    }

    drawField(ctx) {
        ctx.strokeStyle = this.colors.fieldLineBright;
        ctx.lineWidth = 2;
        ctx.beginPath();
        ctx.rect(-this.fieldWidth, -this.fieldHeight, this.fieldWidth * 2, this.fieldHeight * 2);
        ctx.stroke();
        ctx.beginPath();
        ctx.moveTo(0, -this.fieldHeight);
        ctx.lineTo(0, this.fieldHeight);
        ctx.stroke();
        ctx.beginPath();
        ctx.arc(0, 0, this.kickOffRadius, 0, Math.PI * 2);
        ctx.stroke();
        ctx.fillStyle = this.colors.fieldLineBright;
        ctx.beginPath();
        ctx.arc(0, 0, 4, 0, Math.PI * 2);
        ctx.fill();

        // Goal areas
        ctx.fillStyle = this.colors.goalRed;
        ctx.fillRect(-this.borderX - this.goalWidth, -this.goalPostY, this.goalWidth, this.goalPostY * 2);
        ctx.fillStyle = this.colors.goalBlue;
        ctx.fillRect(this.borderX, -this.goalPostY, this.goalWidth, this.goalPostY * 2);

        this.drawNetLines(ctx, -this.borderX - this.goalWidth, -this.goalPostY, this.goalWidth, this.goalPostY * 2, this.colors.goalNetRed);
        this.drawNetLines(ctx, this.borderX, -this.goalPostY, this.goalWidth, this.goalPostY * 2, this.colors.goalNetBlue);
    }

    drawNetLines(ctx, x, y, w, h, color) {
        ctx.strokeStyle = color;
        ctx.lineWidth = 1;
        ctx.globalAlpha = 0.3;
        const spacing = 10;
        for (let nx = x; nx <= x + w; nx += spacing) {
            ctx.beginPath();
            ctx.moveTo(nx, y);
            ctx.lineTo(nx, y + h);
            ctx.stroke();
        }
        for (let ny = y; ny <= y + h; ny += spacing) {
            ctx.beginPath();
            ctx.moveTo(x, ny);
            ctx.lineTo(x + w, ny);
            ctx.stroke();
        }
        ctx.globalAlpha = 1;
    }

    drawSegments(ctx) {
        ctx.strokeStyle = this.colors.wall;
        ctx.lineWidth = 3;
        // Left walls
        ctx.beginPath(); ctx.moveTo(-this.borderX, -this.borderY); ctx.lineTo(-this.borderX, -this.goalPostY); ctx.stroke();
        ctx.beginPath(); ctx.moveTo(-this.borderX, this.goalPostY); ctx.lineTo(-this.borderX, this.borderY); ctx.stroke();
        // Right walls
        ctx.beginPath(); ctx.moveTo(this.borderX, -this.borderY); ctx.lineTo(this.borderX, -this.goalPostY); ctx.stroke();
        ctx.beginPath(); ctx.moveTo(this.borderX, this.goalPostY); ctx.lineTo(this.borderX, this.borderY); ctx.stroke();
        // Goal nets
        ctx.lineWidth = 2;
        ctx.strokeStyle = this.colors.goalNetRed;
        ctx.beginPath();
        ctx.moveTo(-this.borderX, -this.goalPostY);
        ctx.lineTo(-this.borderX - this.goalWidth, -this.goalPostY);
        ctx.lineTo(-this.borderX - this.goalWidth, this.goalPostY);
        ctx.lineTo(-this.borderX, this.goalPostY);
        ctx.stroke();
        ctx.strokeStyle = this.colors.goalNetBlue;
        ctx.beginPath();
        ctx.moveTo(this.borderX, -this.goalPostY);
        ctx.lineTo(this.borderX + this.goalWidth, -this.goalPostY);
        ctx.lineTo(this.borderX + this.goalWidth, this.goalPostY);
        ctx.lineTo(this.borderX, this.goalPostY);
        ctx.stroke();
        // Top/bottom walls
        ctx.strokeStyle = this.colors.wall;
        ctx.lineWidth = 3;
        ctx.beginPath(); ctx.moveTo(-this.borderX, -this.borderY); ctx.lineTo(this.borderX, -this.borderY); ctx.stroke();
        ctx.beginPath(); ctx.moveTo(-this.borderX, this.borderY); ctx.lineTo(this.borderX, this.borderY); ctx.stroke();
    }

    drawGoalPosts(ctx) {
        const posts = [
            { x: -this.borderX, y: -this.goalPostY, color: '#e56e56' },
            { x: -this.borderX, y: this.goalPostY, color: '#e56e56' },
            { x: this.borderX, y: -this.goalPostY, color: '#5689e5' },
            { x: this.borderX, y: this.goalPostY, color: '#5689e5' },
        ];
        for (const post of posts) {
            ctx.beginPath(); ctx.arc(post.x, post.y, 12, 0, Math.PI * 2);
            ctx.fillStyle = post.color + '40'; ctx.fill();
            ctx.beginPath(); ctx.arc(post.x, post.y, 8, 0, Math.PI * 2);
            ctx.fillStyle = post.color; ctx.fill();
            ctx.beginPath(); ctx.arc(post.x - 2, post.y - 2, 3, 0, Math.PI * 2);
            ctx.fillStyle = 'rgba(255,255,255,0.3)'; ctx.fill();
        }
    }

    drawDiscs(ctx, state, prevState, alpha) {
        const playerDiscs = [];
        let ballDisc = null;

        for (let i = 0; i < state.discs.length; i++) {
            const disc = state.discs[i];
            if (disc.isBall) {
                ballDisc = { disc, index: i };
            } else {
                playerDiscs.push({ disc, index: i });
            }
        }

        // Draw players
        for (const { disc, index } of playerDiscs) {
            let x = disc.x;
            let y = disc.y;

            if (prevState && prevState.discs && prevState.discs[index]) {
                const prev = prevState.discs[index];
                x = prev.x + (disc.x - prev.x) * alpha;
                y = prev.y + (disc.y - prev.y) * alpha;
            }

            this.drawPlayer(ctx, x, y, disc, state.playerMap[index]);
        }

        // Draw ball
        if (ballDisc) {
            let x = ballDisc.disc.x;
            let y = ballDisc.disc.y;
            if (prevState && prevState.discs && prevState.discs[ballDisc.index]) {
                const prev = prevState.discs[ballDisc.index];
                x = prev.x + (ballDisc.disc.x - prev.x) * alpha;
                y = prev.y + (ballDisc.disc.y - prev.y) * alpha;
            }
            this.drawBall(ctx, x, y, ballDisc.disc);
        }
    }

    drawPlayer(ctx, x, y, disc, playerInfo) {
        const radius = disc.radius;
        const color = '#' + disc.color;
        const isKicking = disc.isKicking;

        // Shadow
        ctx.beginPath();
        ctx.arc(x + 2, y + 2, radius, 0, Math.PI * 2);
        ctx.fillStyle = 'rgba(0, 0, 0, 0.2)';
        ctx.fill();

        // KICK RING: translucent ring around player, white when kicking
        const ringRadius = radius + 5;
        ctx.beginPath();
        ctx.arc(x, y, ringRadius, 0, Math.PI * 2);
        ctx.lineWidth = 3;
        if (isKicking) {
            // White glowing ring when kicking
            ctx.strokeStyle = 'rgba(255, 255, 255, 0.95)';
            ctx.shadowColor = '#ffffff';
            ctx.shadowBlur = 12;
        } else {
            // Subtle translucent ring normally
            ctx.strokeStyle = color + '50';
            ctx.shadowColor = 'transparent';
            ctx.shadowBlur = 0;
        }
        ctx.stroke();
        ctx.shadowColor = 'transparent';
        ctx.shadowBlur = 0;

        // Player disc body
        ctx.beginPath();
        ctx.arc(x, y, radius, 0, Math.PI * 2);
        ctx.fillStyle = color;
        ctx.fill();
        ctx.strokeStyle = 'rgba(0,0,0,0.3)';
        ctx.lineWidth = 2;
        ctx.stroke();

        // Inner highlight
        const gradient = ctx.createRadialGradient(
            x - radius * 0.2, y - radius * 0.2, 0,
            x, y, radius
        );
        gradient.addColorStop(0, 'rgba(255,255,255,0.25)');
        gradient.addColorStop(1, 'rgba(255,255,255,0)');
        ctx.beginPath();
        ctx.arc(x, y, radius * 0.8, 0, Math.PI * 2);
        ctx.fillStyle = gradient;
        ctx.fill();

        // Player name
        if (playerInfo && playerInfo.name) {
            ctx.font = 'bold 11px Inter, sans-serif';
            ctx.textAlign = 'center';
            ctx.textBaseline = 'middle';
            const nameWidth = ctx.measureText(playerInfo.name).width;
            const nameY = y - radius - 14;
            ctx.fillStyle = 'rgba(0,0,0,0.6)';
            ctx.beginPath();
            ctx.roundRect(x - nameWidth / 2 - 4, nameY - 7, nameWidth + 8, 14, 3);
            ctx.fill();
            ctx.fillStyle = '#ffffff';
            ctx.fillText(playerInfo.name, x, nameY);
        }
    }

    drawBall(ctx, x, y, disc) {
        const radius = disc.radius;
        ctx.beginPath();
        ctx.arc(x + 1, y + 1, radius + 1, 0, Math.PI * 2);
        ctx.fillStyle = 'rgba(0, 0, 0, 0.3)';
        ctx.fill();
        ctx.beginPath();
        ctx.arc(x, y, radius + 2, 0, Math.PI * 2);
        ctx.fillStyle = 'rgba(255, 255, 255, 0.15)';
        ctx.fill();
        ctx.beginPath();
        ctx.arc(x, y, radius, 0, Math.PI * 2);
        ctx.fillStyle = '#ffffff';
        ctx.fill();
        ctx.strokeStyle = '#333333';
        ctx.lineWidth = 1.5;
        ctx.stroke();
        // Ball pattern
        ctx.fillStyle = '#dddddd';
        const angles = [0, 72, 144, 216, 288];
        for (const angle of angles) {
            const rad = (angle * Math.PI) / 180;
            const px = x + Math.cos(rad) * radius * 0.55;
            const py = y + Math.sin(rad) * radius * 0.55;
            ctx.beginPath();
            ctx.arc(px, py, radius * 0.22, 0, Math.PI * 2);
            ctx.fill();
        }
        ctx.beginPath();
        ctx.arc(x - radius * 0.25, y - radius * 0.25, radius * 0.35, 0, Math.PI * 2);
        ctx.fillStyle = 'rgba(255,255,255,0.5)';
        ctx.fill();
    }
}
