class_name WorldPlayer extends Resource
## Container for the state of the player within the world.

signal on_life_changed(new_value: float)
signal on_balls_changed(type: GameBall.Type, new_value: int)
signal on_death(player: WorldPlayer)

const MAX_LIFE := 100.0

@export_range(0, MAX_LIFE) var life: float = MAX_LIFE:
	set(value):
		if value != life:
			life = value
			on_life_changed.emit(value)

@export_category("Profile")
# TODO character select
@export var name: String = "Gfolfer"
@export var color: Color = Color("ff7070")

@export_category("Equipment")
@export var driver: Club
@export var iron: Club
@export var wedge: Club
@export var putter: Club
@export var special: Club

## Count of each type of ball the player possesses.
## A count of less than zero indicates unlimited quantity.
@export var _balls := {
	GameBall.Type.BASIC: -1,
	GameBall.Type.PLASMA: -1,
}

var shot_setup: ShotSetup:
	get:
		if not shot_setup:
			shot_setup = ShotSetup.create(self)
		return shot_setup


## Get the club equipped in the given slot.
##
## Returns `null` if the player has no club equipped in the given slot
func get_club(type: Club.Type) -> Club:
	match type:
		Club.Type.DRIVER:
			return driver
		Club.Type.IRON:
			return iron
		Club.Type.WEDGE:
			return wedge
		Club.Type.PUTTER:
			return putter
		Club.Type.SPECIAL:
			return special
	return null


## Get the quantity of a ball type
func get_balls(type: GameBall.Type) -> int:
	return _balls.get(type, 0)


## Set the quantity of a ball type
func set_balls(type: GameBall.Type, value: int) -> void:
	_balls[type] = value
	on_balls_changed.emit(type, value)


## Change the quantity of a ball type
func mutate_balls(type: GameBall.Type, delta: int) -> void:
	if _balls.get(type, 0) >= 0:
		_balls[type] = _balls.get(type, 0) + delta
		on_balls_changed.emit(type, _balls[type])


## Get next slotted ball type
func next_ball(type: GameBall.Type) -> GameBall.Type:
	var keys := _balls.keys()
	var i := keys.find(type)
	var j := (i + 1) % len(keys) if i >= 0 else 0
	return keys[j]


## Get previous slotted ball type
func prev_ball(type: GameBall.Type) -> GameBall.Type:
	var keys := _balls.keys()
	var i := keys.find(type)
	var j := (i - 1) % len(keys) if i >= 0 else 0
	return keys[j]


## Restore life up to the MAX_LIFE cap.
## If the player's life is greater than or equal to MAX_LIFE, they will not be healed.
func heal(amount: float) -> void:
	life += minf(amount, maxf(MAX_LIFE - life, 0))


func die() -> void:
	on_death.emit(self)


func deconstruct() -> void:
	if is_instance_valid(shot_setup):
		shot_setup.queue_free()


## Create a debug player instance
static func create_debug() -> WorldPlayer:
	var instance := WorldPlayer.new()
	instance.driver = Club.catalog.debug_driver
	instance.iron = Club.catalog.debug_iron
	instance.wedge = Club.catalog.debug_wedge
	instance.putter = Club.catalog.debug_wedge

	return instance
