"""
3D Particle system for firework effects.
"""

from typing import Tuple


class Particle:
    """A 3D particle with position, velocity, and lifetime."""

    def __init__(
        self,
        x: float,
        y: float,
        z: float,
        vx: float,
        vy: float,
        vz: float,
        color: str,
        lifetime: float,
    ):
        """
        Initialize a particle.

        Args:
            x, y, z: Initial 3D position
            vx, vy, vz: Initial 3D velocity
            color: RGB color string
            lifetime: Time in seconds before particle disappears
        """
        self.x = x
        self.y = y
        self.z = z
        self.vx = vx
        self.vy = vy
        self.vz = vz
        self.color = color
        self.lifetime = lifetime
        self.age = 0.0

    def update(self, dt: float, gravity: float = 50.0, air_resistance: float = 0.97):
        """
        Update particle position and age.

        Args:
            dt: Time delta in seconds
            gravity: Gravity acceleration (pixels/s^2)
            air_resistance: Air resistance factor (0-1, closer to 1 = less resistance)
        """
        # Apply gravity to vertical velocity
        self.vy += gravity * dt

        # Apply air resistance (damping) to all velocities
        self.vx *= air_resistance
        self.vy *= air_resistance
        self.vz *= air_resistance

        # Update position
        self.x += self.vx * dt
        self.y += self.vy * dt
        self.z += self.vz * dt

        # Update age
        self.age += dt

    def is_alive(self) -> bool:
        """Check if particle is still alive."""
        return self.age < self.lifetime

    def get_2d_position(
        self,
        camera_distance: float = 200.0,
        center_x: float = 0.0,
        center_y: float = 0.0,
    ) -> Tuple[int, int]:
        """
        Get 2D screen position with perspective projection.

        Args:
            camera_distance: Distance of camera from z=0 plane
            center_x: X coordinate of screen center
            center_y: Y coordinate of screen center

        Returns:
            (x, y) screen coordinates
        """
        z_offset = self.z + camera_distance

        if z_offset <= 0:
            # Particle is behind camera, don't render
            return (-1, -1)

        # Apply perspective scaling relative to screen center
        scale = camera_distance / z_offset

        # Project relative to center, then add center back
        screen_x = center_x + (self.x - center_x) * scale
        screen_y = center_y + (self.y - center_y) * scale

        return (int(screen_x), int(screen_y))
