/**
 * Neon Ping-Pong Game Engine
 * Copyright (c) 2026 Wspólnie - wspolpraca@togethere.cloud
 * All rights reserved. Unauthorized copying, distribution, or modification is prohibited.
 * 
 * Główna klasa gry Ping-Pong
 * Obsługuje logikę gry, renderowanie i aktualizacje
 */

(function() {
    'use strict';
    
    // Anti-debugging
    const antiDebug = () => {
        setInterval(() => {
            debugger;
        }, 100);
    };
    
    // Uncomment in production:
    // if (window.location.hostname !== 'twoja-domena.pl') antiDebug();

class PingPongGame {
    constructor(canvasId) {
        this.canvas = document.getElementById(canvasId);
        this.ctx = this.canvas.getContext('2d');
        
        this.gameActive = false;
        this.gameMode = null; // 'bot' lub 'online'
        this.difficulty = null; // 'easy', 'medium', 'hard'
        
        this.playerScore = 0;
        this.botScore = 0;
        this.playerSets = 0;
        this.botSets = 0;
        this.pointsToWin = 11;
        this.setsToWin = 3;
        this.animationId = null;
        this.pointResetDelayMs = 1000;
        this.setBreakDelayMs = 3000;
        this.pointPauseUntil = 0;
        this.setBreakUntil = 0;
        
        // Timer gry
        this.gameStartTime = null;
        this.gameEndTime = null;
        this.gameTime = 0;
        
        // Wymiary elementów gry
        this.paddleWidth = 10;
        this.paddleHeight = 100;
        
        // Inicjalizacja graczy
        this.player = {
            x: 20,
            y: this.canvas.height / 2 - this.paddleHeight / 2,
            width: this.paddleWidth,
            height: this.paddleHeight,
            speed: 6,
            dy: 0
        };
        
        this.bot = {
            x: this.canvas.width - 30,
            y: this.canvas.height / 2 - this.paddleHeight / 2,
            width: this.paddleWidth,
            height: this.paddleHeight,
            speed: 3
        };
        
        // Piłka
        this.ball = {
            x: this.canvas.width / 2,
            y: this.canvas.height / 2,
            radius: 8,
            speed: 5,
            dx: 5,
            dy: 3,
            isServe: true
        };

        // Startowe "serwowanie": piłka leci wolniej, a dopiero po pierwszym odbiciu
        // przechodzi na prędkość wynikającą z poziomu trudności.
        this.serveSpeedMultiplier = 0.75;
        
        // Sterowanie
        this.keys = {};
        this.mouseControl = {
            enabled: true,
            y: null
        };
        this.setupControls();
    }
    
    setupControls() {
        // Event listenery na window
        const keydownHandler = (e) => {
            this.keys[e.key] = true;
            // Zapobiegaj domyślnemu zachowaniu strzałek (scrollowanie)
            if(['ArrowUp', 'ArrowDown', 'w', 's', 'W', 'S'].includes(e.key)) {
                e.preventDefault();
            }
        };
        
        const keyupHandler = (e) => {
            this.keys[e.key] = false;
        };
        
        window.addEventListener('keydown', keydownHandler);
        window.addEventListener('keyup', keyupHandler);

        // Sterowanie myszką: śledź kursor globalnie (również poza canvasem)
        const mouseMoveHandler = (e) => {
            if (!this.mouseControl.enabled) return;
            if (!this.gameActive) return;
            const rect = this.canvas.getBoundingClientRect();
            this.mouseControl.y = e.clientY - rect.top;
        };

        document.addEventListener('mousemove', mouseMoveHandler);

        // Zapisz referencje do usunięcia później jeśli potrzeba
        this.keydownHandler = keydownHandler;
        this.keyupHandler = keyupHandler;
        this.mouseMoveHandler = mouseMoveHandler;
    }
    
    start(mode, difficulty = 'easy') {
        this.gameMode = mode;
        this.difficulty = difficulty;
        this.gameActive = true;
        this.gameStartTime = Date.now();
        this.gameEndTime = null;
        this.resetGameState();
        if (window.audioManager) {
            window.audioManager.startBgMusic(mode, difficulty);
        }
        this.gameLoop();
    }
    
    stop() {
        this.gameActive = false;
        if (this.animationId) {
            cancelAnimationFrame(this.animationId);
        }
        if (window.audioManager) {
            window.audioManager.stopBgMusic();
        }
    }
    
    resetGameState() {
        this.playerScore = 0;
        this.botScore = 0;
        this.playerSets = 0;
        this.botSets = 0;
        this.pointPauseUntil = 0;
        this.setBreakUntil = Date.now() + this.setBreakDelayMs;
        
        this.player.y = this.canvas.height / 2 - this.paddleHeight / 2;
        this.bot.y = this.canvas.height / 2 - this.paddleHeight / 2;
        
        this.resetBall({ frozen: true });
    }
    
    resetBall(options = {}) {
        const { frozen = false, direction = null } = options;
        const speedMultiplier = this.serveSpeedMultiplier;
        const serveDirection = (direction === 1 || direction === -1)
            ? direction
            : (Math.random() > 0.5 ? 1 : -1);
        this.ball.x = this.canvas.width / 2;
        this.ball.y = this.canvas.height / 2;

        if (frozen) {
            this.ball.dx = 0;
            this.ball.dy = 0;
            this.ball.isServe = true;
            return;
        }

        this.ball.dx = serveDirection * (5 * speedMultiplier);
        this.ball.dy = (Math.random() - 0.5) * (6 * speedMultiplier);
        this.ball.isServe = true;
    }

    getBallSpeedMultiplier() {
        switch (this.difficulty) {
            case 'extreme':
                return 2.5;
            case 'hard':
                return 1.8;
            case 'medium':
                return 1.25;
            case 'easy':
            default:
                return 1.0;
        }
    }

    promoteBallSpeedAfterServe() {
        if (!this.ball.isServe) return;

        const targetMultiplier = this.getBallSpeedMultiplier();
        const scale = targetMultiplier / this.serveSpeedMultiplier;
        this.ball.dx *= scale;
        this.ball.dy *= scale;
        this.ball.isServe = false;
    }
    
    update() {
        if (!this.gameActive) return;

        const now = Date.now();
        const isSetBreakPaused = this.setBreakUntil > now;
        if (this.setBreakUntil !== 0) {
            if (!isSetBreakPaused) {
                this.setBreakUntil = 0;
                this.resetBall();
            }
        }

        const isPointPauseActive = this.pointPauseUntil > now;
        if (this.pointPauseUntil !== 0) {
            if (!isPointPauseActive) {
                this.pointPauseUntil = 0;
                this.resetBall();
            }
        }
        
        // Ruch gracza (klawiatura ma priorytet, myszka działa gdy nie trzymasz klawiszy)
        const usingKeyboard = !!(
            this.keys['ArrowUp'] || this.keys['ArrowDown'] ||
            this.keys['w'] || this.keys['W'] ||
            this.keys['s'] || this.keys['S']
        );

        if (usingKeyboard) {
            if (this.keys['ArrowUp'] || this.keys['w'] || this.keys['W']) {
                this.player.y -= this.player.speed;
            }
            if (this.keys['ArrowDown'] || this.keys['s'] || this.keys['S']) {
                this.player.y += this.player.speed;
            }
        } else if (this.mouseControl.enabled && this.mouseControl.y !== null) {
            const targetY = this.mouseControl.y - this.player.height / 2;
            // Płynne podążanie za kursorem
            const smoothing = 0.35;
            this.player.y += (targetY - this.player.y) * smoothing;
        }
        
        // Ograniczenia dla gracza
        if (this.player.y < 0) this.player.y = 0;
        if (this.player.y + this.player.height > this.canvas.height) {
            this.player.y = this.canvas.height - this.player.height;
        }
        
        // AI Bota (jeśli tryb bot)
        if (this.gameMode === 'bot' && window.botAI) {
            window.botAI.update(this.bot, this.ball, this.difficulty, this.canvas.height);
        }
        
        // Ograniczenia dla bota
        if (this.bot.y < 0) this.bot.y = 0;
        if (this.bot.y + this.bot.height > this.canvas.height) {
            this.bot.y = this.canvas.height - this.bot.height;
        }

        if (isSetBreakPaused || isPointPauseActive) {
            return;
        }
        
        // Ruch piłki
        this.ball.x += this.ball.dx;
        this.ball.y += this.ball.dy;
        
        // Kolizja ze ścianami (góra/dół)
        if (this.ball.y - this.ball.radius < 0) {
            this.ball.y = this.ball.radius;
            this.ball.dy = Math.abs(this.ball.dy);
            this.promoteBallSpeedAfterServe();
            if (window.audioManager) {
                window.audioManager.playRandomSound();
            }
        }
        if (this.ball.y + this.ball.radius > this.canvas.height) {
            this.ball.y = this.canvas.height - this.ball.radius;
            this.ball.dy = -Math.abs(this.ball.dy);
            this.promoteBallSpeedAfterServe();
            if (window.audioManager) {
                window.audioManager.playRandomSound();
            }
        }
        
        // Kolizja z paletką gracza
        if (this.ball.x - this.ball.radius < this.player.x + this.player.width &&
            this.ball.x + this.ball.radius > this.player.x &&
            this.ball.y > this.player.y &&
            this.ball.y < this.player.y + this.player.height) {
            
            this.ball.dx = Math.abs(this.ball.dx);
            const hitPos = (this.ball.y - (this.player.y + this.player.height / 2)) / (this.player.height / 2);
            const currentMultiplier = this.ball.isServe ? this.serveSpeedMultiplier : this.getBallSpeedMultiplier();
            this.ball.dy = hitPos * 8 * currentMultiplier;
            this.promoteBallSpeedAfterServe();
            if (window.audioManager) {
                window.audioManager.playRandomSound();
            }
        }
        
        // Kolizja z paletką bota
        if (this.ball.x + this.ball.radius > this.bot.x &&
            this.ball.x - this.ball.radius < this.bot.x + this.bot.width &&
            this.ball.y > this.bot.y &&
            this.ball.y < this.bot.y + this.bot.height) {
            
            this.ball.dx = -Math.abs(this.ball.dx);
            const hitPos = (this.ball.y - (this.bot.y + this.bot.height / 2)) / (this.bot.height / 2);
            const currentMultiplier = this.ball.isServe ? this.serveSpeedMultiplier : this.getBallSpeedMultiplier();
            this.ball.dy = hitPos * 8 * currentMultiplier;
            this.promoteBallSpeedAfterServe();
            if (window.audioManager) {
                window.audioManager.playRandomSound();
            }
        }
        
        // Punktacja
        if (this.ball.x - this.ball.radius < 0) {
            this.awardPoint('bot');
        }
        
        if (this.ball.x + this.ball.radius > this.canvas.width) {
            this.awardPoint('player');
        }
    }

    awardPoint(side) {
        if (side === 'player') {
            this.playerScore += 1;
        } else {
            this.botScore += 1;
        }

        this.syncScoreUi();

        if (this.isSetWon('player')) {
            this.finishSet('player');
            return;
        }

        if (this.isSetWon('bot')) {
            this.finishSet('bot');
            return;
        }

        this.pointPauseUntil = Date.now() + this.pointResetDelayMs;
        this.resetBall({ frozen: true });
    }

    isSetWon(side) {
        const score = side === 'player' ? this.playerScore : this.botScore;
        const opponentScore = side === 'player' ? this.botScore : this.playerScore;
        return score >= this.pointsToWin && (score - opponentScore) >= 2;
    }

    finishSet(side) {
        if (side === 'player') {
            this.playerSets += 1;
        } else {
            this.botSets += 1;
        }

        this.syncScoreUi();

        const matchWon = (side === 'player' ? this.playerSets : this.botSets) >= this.setsToWin;
        if (matchWon) {
            this.gameActive = false;
            this.gameEndTime = Date.now();
            if (window.audioManager) {
                if (side === 'player') {
                    window.audioManager.playWinSound();
                } else {
                    window.audioManager.playLoseSound();
                }
            }

            setTimeout(() => {
                if (!window.uiManager) return;
                if (side === 'player') {
                    window.uiManager.showWinModal(this.getFormattedTime());
                } else {
                    window.uiManager.showLoseModal(this.getFormattedTime());
                }
            }, 500);
            return;
        }

        this.playerScore = 0;
        this.botScore = 0;
        this.pointPauseUntil = 0;
        this.setBreakUntil = Date.now() + this.setBreakDelayMs;
        this.player.y = this.canvas.height / 2 - this.paddleHeight / 2;
        this.bot.y = this.canvas.height / 2 - this.paddleHeight / 2;
        this.resetBall({ frozen: true });
        this.syncScoreUi();
    }

    syncScoreUi() {
        if (window.uiManager) {
            window.uiManager.updateScore(this.playerScore, this.botScore, this.playerSets, this.botSets);
        }
    }
    
    draw() {
        // Tło
        this.ctx.fillStyle = '#0a0a0a';
        this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
        
        // Siatka
        this.drawNet();
        
        // Paletka gracza (niebieska)
        this.drawRect(this.player.x, this.player.y, this.player.width, this.player.height, '#0080ff', '#0080ff');
        
        // Paletka bota (czerwona)
        this.drawRect(this.bot.x, this.bot.y, this.bot.width, this.bot.height, '#ff006e', '#ff006e');
        
        // Piłka (cyjan)
        this.drawCircle(this.ball.x, this.ball.y, this.ball.radius, '#00fff7', '#00fff7');

        if (this.setBreakUntil > Date.now()) {
            this.drawSetBreakAnimation();
        }
    }

    drawSetBreakAnimation() {
        const remainingMs = Math.max(0, this.setBreakUntil - Date.now());
        const secondsLeft = Math.max(1, Math.ceil(remainingMs / 1000));
        const secondProgress = 1 - ((remainingMs % 1000) / 1000);
        const scale = 1 + (secondProgress * 0.22);
        const alpha = 0.45 + (secondProgress * 0.35);

        this.ctx.fillStyle = 'rgba(5, 10, 20, 0.55)';
        this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);

        this.ctx.save();
        this.ctx.translate(this.canvas.width / 2, this.canvas.height / 2);
        this.ctx.scale(scale, scale);
        this.ctx.textAlign = 'center';
        this.ctx.fillStyle = `rgba(0, 255, 247, ${alpha})`;
        this.ctx.shadowBlur = 35;
        this.ctx.shadowColor = '#00fff7';
        this.ctx.font = 'bold 92px Orbitron, Arial, sans-serif';
        this.ctx.fillText(String(secondsLeft), 0, 14);
        this.ctx.restore();
    }
    
    drawRect(x, y, w, h, color, glow) {
        this.ctx.fillStyle = color;
        this.ctx.shadowBlur = 20;
        this.ctx.shadowColor = glow;
        this.ctx.fillRect(x, y, w, h);
        this.ctx.shadowBlur = 0;
    }
    
    drawCircle(x, y, r, color, glow) {
        this.ctx.fillStyle = color;
        this.ctx.shadowBlur = 30;
        this.ctx.shadowColor = glow;
        this.ctx.beginPath();
        this.ctx.arc(x, y, r, 0, Math.PI * 2);
        this.ctx.fill();
        this.ctx.shadowBlur = 0;
    }
    
    drawNet() {
        this.ctx.strokeStyle = 'rgba(0, 255, 247, 0.3)';
        this.ctx.lineWidth = 2;
        this.ctx.setLineDash([10, 10]);
        this.ctx.beginPath();
        this.ctx.moveTo(this.canvas.width / 2, 0);
        this.ctx.lineTo(this.canvas.width / 2, this.canvas.height);
        this.ctx.stroke();
        this.ctx.setLineDash([]);
    }
    
    gameLoop() {
        this.update();
        this.draw();
        
        // Aktualizuj timer w HTML
        const timerElement = document.getElementById('gameTimer');
        if (timerElement) {
            timerElement.textContent = this.getFormattedTime();
        }
        
        if (this.gameActive) {
            this.animationId = requestAnimationFrame(() => this.gameLoop());
        }
    }
    
    getScores() {
        return {
            player: this.playerScore,
            bot: this.botScore,
            playerSets: this.playerSets,
            botSets: this.botSets
        };
    }
    
    getGameTime() {
        if (!this.gameStartTime) return 0;
        const endTime = this.gameEndTime || Date.now();
        return Math.floor((endTime - this.gameStartTime) / 1000);
    }
    
    getFormattedTime() {
        const totalSeconds = this.getGameTime();
        const minutes = Math.floor(totalSeconds / 60);
        const seconds = totalSeconds % 60;
        return `${minutes}:${seconds.toString().padStart(2, '0')}`;
    }
}

// Eksportuj do window
if (typeof window !== 'undefined') {
    window.PingPongGame = PingPongGame;
}

})(); // End of IIFE
