@icon("res://composants/objets/balle/SphereShape3D.svg")
class_name Balle
extends CharacterBody2D


signal rebondi

const ratio_diff_angle: float = PI * 0.005 # radian / px
const ascension_min: float = 10.0 # px / sec
const vitesse_initiale: float = 100.0 # px / sec
const acceleration_par_touche: float = 50.0 # px / sec / touche

@export var direction_initiale: Vector2 = Vector2.DOWN

var _mouvement: Vector2
var _vitesse: float = vitesse_initiale


func _ready() -> void:
	_mettre_en_mouvement(direction_initiale)


func _physics_process(delta: float) -> void:
	var impact: KinematicCollision2D = move_and_collide(_mouvement * delta)

	if impact == null:
		return # pas d'impact a gerer

	_rebondir(impact)
	var obstacle: Object = impact.get_collider()
	if obstacle is Raquette and en_train_de_monter():
		_orienter_tir(obstacle)
		_accelerer()
	elif obstacle is Brique:
		_impacter_brique(obstacle)


func ralentir(diviseur: float) -> void:
	assert(diviseur > 1.0, "Valeur diviseur invalide pour ralentir")
	_vitesse /= diviseur
	_mettre_en_mouvement(_mouvement.normalized())


## Recopie les proprietes utiles de l'autre balle
func recopier(autre_balle: Balle) -> void:
	position = autre_balle.position
	_vitesse = autre_balle._vitesse
	_mouvement = autre_balle._mouvement
	direction_initiale = _mouvement.normalized() # pour garder direction en cas d'ajout dans une scene


func detruire() -> void:
	queue_free()


func en_train_de_monter() -> bool:
	return _mouvement.y < 0.0


func _rebondir(impact: KinematicCollision2D) -> void:
	_mouvement = _mouvement.bounce(impact.get_normal())
	rebondi.emit()


func _orienter_tir(raquette: Raquette) -> void:
	var difference = global_position.x - raquette.position.x
	_mouvement = Vector2.UP.rotated(difference * ratio_diff_angle) * _mouvement.length()

	# empeche la balle de monter trop lentement
	_mouvement.y = min(_mouvement.y, -ascension_min)


func _accelerer() -> void:
	_vitesse += acceleration_par_touche
	_mettre_en_mouvement(_mouvement.normalized())


func _impacter_brique(brique: Brique) -> void:
	brique.frapper(1)


## Permet d'appliquer la vitesse dans la direction voulue
## si la direction est inchangée, donnez _mouvement.normalized()
func _mettre_en_mouvement(dir: Vector2) -> void:
	_mouvement = dir * _vitesse
