/**
 * Projectile.js
 * Helper for managing projectiles (fireballs, boss shots, etc.)
 * Handles movement, collision, and lifetime
 */

export class Projectile {
    /**
     * Update all projectiles
     * @param {Array} projectiles - Array of projectiles
     * @param {Object} mario - Mario object
     * @param {Array} platforms - Platforms for collision
     * @param {Array} walls - Walls for collision
     * @param {number} levelWidth - Level width for bounds checking
     * @param {Function} onMarioHit - Callback when Mario is hit
     * @param {Function} onObstacleHit - Callback when projectile hits obstacle
     * @returns {Array} - Updated projectiles array
     */
    static update(projectiles, mario, platforms, walls, levelWidth, onMarioHit, onObstacleHit) {
        const updatedProjectiles = [];

        projectiles.forEach((projectile, index) => {
            // Update position
            projectile.x += projectile.velocityX;
            projectile.y += projectile.velocityY;
            projectile.life--;

            // Remove projectiles that are off-screen or expired
            if (projectile.life <= 0 || projectile.x < -50 || projectile.x > levelWidth + 50) {
                return; // Don't add to updated array (remove)
            }

            // Check collision with Mario
            if (this._isCollidingCircleRect(projectile, mario)) {
                if (onMarioHit) {
                    onMarioHit(projectile);
                }
                return; // Remove projectile
            }

            // Check collision with walls/platforms
            const hitPlatform = platforms.some(platform =>
                this._isCollidingCircleRect(projectile, platform)
            );
            const hitWall = walls.some(wall =>
                this._isCollidingCircleRect(projectile, wall)
            );

            if (hitPlatform || hitWall) {
                if (onObstacleHit) {
                    onObstacleHit(projectile, index, projectile.x, projectile.y);
                }
                return; // Remove projectile
            }

            // Keep projectile if no collision
            updatedProjectiles.push(projectile);
        });

        return updatedProjectiles;
    }

    /**
     * Create a new projectile
     * @param {number} x - Start X position
     * @param {number} y - Start Y position
     * @param {number} velocityX - Horizontal velocity
     * @param {number} velocityY - Vertical velocity
     * @param {Object} options - Additional options (radius, color, type, life)
     * @returns {Object} - Projectile object
     */
    static create(x, y, velocityX, velocityY, options = {}) {
        return {
            x: x,
            y: y,
            velocityX: velocityX,
            velocityY: velocityY,
            radius: options.radius || 8,
            color: options.color || '#FF4500',
            type: options.type || 'projectile',
            life: options.life || 200
        };
    }

    /**
     * Create a projectile aimed at a target
     * @param {number} fromX - Start X
     * @param {number} fromY - Start Y
     * @param {number} toX - Target X
     * @param {number} toY - Target Y
     * @param {number} speed - Projectile speed
     * @param {Object} options - Additional options
     * @returns {Object} - Projectile object
     */
    static createAimed(fromX, fromY, toX, toY, speed, options = {}) {
        const dx = toX - fromX;
        const dy = toY - fromY;
        const distance = Math.sqrt(dx * dx + dy * dy);

        const velocityX = (dx / distance) * speed;
        const velocityY = (dy / distance) * speed;

        return this.create(fromX, fromY, velocityX, velocityY, options);
    }

    /**
     * Circle-Rectangle collision detection
     * @param {Object} circle - Circle object with x, y, radius
     * @param {Object} rect - Rectangle object with x, y, width, height
     * @returns {boolean} - True if colliding
     */
    static _isCollidingCircleRect(circle, rect) {
        const closestX = Math.max(rect.x, Math.min(circle.x, rect.x + rect.width));
        const closestY = Math.max(rect.y, Math.min(circle.y, rect.y + rect.height));

        const distanceX = circle.x - closestX;
        const distanceY = circle.y - closestY;

        const distanceSquared = distanceX * distanceX + distanceY * distanceY;
        return distanceSquared < (circle.radius * circle.radius);
    }

    /**
     * Check if a projectile is out of bounds
     * @param {Object} projectile - Projectile to check
     * @param {number} levelWidth - Level width
     * @param {number} canvasHeight - Canvas height
     * @returns {boolean} - True if out of bounds
     */
    static isOutOfBounds(projectile, levelWidth, canvasHeight) {
        return projectile.x < -50 ||
               projectile.x > levelWidth + 50 ||
               projectile.y < -50 ||
               projectile.y > canvasHeight + 50;
    }

    /**
     * Check if projectile has expired
     * @param {Object} projectile - Projectile to check
     * @returns {boolean} - True if expired
     */
    static isExpired(projectile) {
        return projectile.life <= 0;
    }
}

export default Projectile;
