from __future__ import annotations
from typing import Self

from .. import config
from ..math_util import *

from . import level
from .marble import MARBLE, Marble



class PARTICLE:
	SMOKE       = 1
	LASER       = 2
	MARBLE_SELF = 3
	MARBLE_EVIL = 4

class Particle:
	def __init__( self:Self, type:PARTICLE, pos:Vector3,radius:float, vel:Vector3 ):
		self.type = type

		self.pos = Vector3(pos)
		self.radius = radius

		self.vel = Vector3(vel)

		self.time = 0.0

	@staticmethod
	def make_smoke( pos:Vector3, vz:float ):
		vel = Vector3( #TODO: better
			random.uniform( -0.002, 0.002 ),
			random.uniform( -0.002, 0.002 ),
			vz
		)
		return Particle( PARTICLE.SMOKE, pos,0.01, vel )
	@staticmethod
	def make_laser( wall:level.Wall ):
		pos = Vector3( wall.coord.x+random.uniform(), wall.coord.y+random.uniform(), 1.0 )
		return Particle( PARTICLE.LASER, pos, 0.05, Vector3(0.0,0.0,1.0) )
	@staticmethod
	def make_marble( marble:Marble ):
		vec = random_sphere()
		pos = marble.center + vec*marble.radius
		radius = random.uniform(0.1,0.3) * marble.radius
		vel = random.uniform(2.0,5.0) * vec
		vel += marble.vel

		if marble.type == MARBLE.SELF:
			return Particle( PARTICLE.MARBLE_SELF, pos,radius, vel )
		else:
			return Particle( PARTICLE.MARBLE_EVIL, pos,radius, vel )

	def is_active( self:Self ):
		return self.time < 3.0

	def update( self:Self, dt:float ):
		self.time += dt

		if self.type == PARTICLE.SMOKE:
			self.pos += dt * self.vel

			self.radius += dt * 0.03

		elif self.type == PARTICLE.LASER:
			self.pos += dt * self.vel

		else:
			self.vel.x *= 1.0 - 0.6*dt
			self.vel.y *= 1.0 - 0.6*dt
			self.vel.z -= dt * 15.0

			self.pos += dt * self.vel

			#Bounce off ground
			if self.pos.z <= self.radius:
				self.pos.z = self.radius
				self.vel.x *= 0.9
				self.vel.y *= 0.9
				self.vel.z *= -0.75



#class ParticleEmitter:
#	def __init__( self:Self ):
#		pass



particles:list[Particle] = []
#emitters = []

def clear():
	particles.clear()

def explode_marble( marble:Marble ):
	for _ in range(config.particle_num_explode):
		particles.append( Particle.make_marble(marble) )

def update( dt:float ):
	global particles

	for particle in particles:
		particle.update(dt)

	particles = [ particle for particle in particles if particle.is_active() ]
