class_name GameBall extends RigidBody3D
## Base class for all gfolf balls

signal entered_water

const TERRAIN_DAMPING_EPSILON := 1e-6
const IRON_DAMPING := 9999.0

## Angular damping while in air
@export var air_damping := 0.0
## Angular damping while in collision with rough terrain
@export var rough_damping := 8.0
## Angular damping for iron balls
@export var iron_damping := 9999.0

## Causes the ball to act more like a brick
@export var iron_ball := false:
	set(value):
		if value:
			physics_material_override = iron_physics
		else:
			physics_material_override = normal_physics
		iron_ball = value

## Base damage inflicted on impact with a player
@export var base_damage := 15.0

var _zones: Array[BallZone] = []

@onready var normal_physics: PhysicsMaterial = preload(
	"res://src/equipment/balls/physics_ball/normal_physics.tres"
)
@onready var iron_physics: PhysicsMaterial = preload(
	"res://src/equipment/balls/physics_ball/iron_physics.tres"
)


## Called by a water area when this ball enters it
func enter_water() -> void:
	entered_water.emit()


func _total_terrain_angular_damping() -> float:
	return _zones.reduce(
		func(a: float, b: BallZone) -> float: return a + b.terrain_angular_damping, 0.0
	)


func _integrate_forces(state: PhysicsDirectBodyState3D) -> void:
	var damping := air_damping
	if iron_ball:
		damping = iron_damping
	elif state.get_contact_count():
		damping = _total_terrain_angular_damping()
		if damping <= TERRAIN_DAMPING_EPSILON:
			damping = rough_damping
	angular_damp = damping


func enter_zone(zone: BallZone) -> void:
	_zones.push_back(zone)

	if zone.water_hazard:
		entered_water.emit()


func exit_zone(zone: BallZone) -> void:
	_zones.erase(zone)
