extends CharacterBody2D

var it: Item = null
@export var sync_has_been_picked_up: bool = false

var friction = 8.0 # Lower values make the slowdown more gradual
var bounceTimer = 0.0
# Z-axis variables
var positionZ = 4.0 # Start slightly in the air
var velocityZ = 10.0 # Initial upward velocity
var accelerationZ = -330.0 # Gravity
var bounceRestitution = 0.3 # How much bounce energy is retained (0-1)
var minBounceVelocity = 60.0 # Minimum velocity needed to bounce

var sync_position := Vector2()
var sync_velocity := Vector2()
var sync_positionZ: float = 4.0


func _ready() -> void:
	add_to_group("loot")
	
	# Initialize item if needed
	if it == null:
		setItem()

func _process(delta: float) -> void:
	if multiplayer.is_server():
		if bounceTimer > 0.0:
			bounceTimer -= delta
			if bounceTimer < 0:
				bounceTimer = 0
				
		# Update vertical movement
		velocityZ += accelerationZ * delta
		positionZ += velocityZ * delta
		
		# Ground collision and bounce
		if positionZ <= 0:
			velocity = velocity.lerp(Vector2.ZERO, 1.0 - exp(-friction * delta)) # only slow down if on floor
			positionZ = 0
			if abs(velocityZ) > minBounceVelocity:
				#Bounce sound here for items:
				#$SfxCoinBounce.volume_db = -1 + (-10-(velocityZ*0.1))
				#$SfxCoinBounce.play()
				velocityZ = -velocityZ * bounceRestitution
			else:
				velocityZ = 0
		
		update_sprite_scale()
		move_and_slide()
	pass

func _physics_process(_delta: float) -> void:
	if multiplayer.is_server():
		for peer_id in multiplayer.get_peers():
			sync_loot.rpc_id(peer_id, position, velocity, positionZ)
	if !multiplayer.is_server():
		position = sync_position
		velocity = sync_velocity
		positionZ = sync_positionZ
		update_sprite_scale()
	pass
	
@rpc("unreliable")
func sync_loot(pos: Vector2, vel: Vector2, posZ: float):
	sync_position = pos
	sync_velocity = vel
	sync_positionZ = posZ
	pass

func update_sprite_scale() -> void:
	# Calculate scale based on height
	# Maximum height will have scale 1.3, ground will have scale 1.0
	var height_factor = positionZ / 50.0 # Assuming 20 is max height
	var posY = 0.0 + (2 * positionZ)
	var sc = 1.0 + (0.8 * height_factor)
	$Sprite2D.scale = Vector2(sc, sc)
	$Sprite2D.position.y = -posY
	pass

func setItem(iItem: Item = null) -> void:
	$Label.visible = false
	if iItem != null:
		it = iItem
	else:
		it = Item.new()
	if $Sprite2D.texture != null or $Sprite2D.texture.resource_path != it.spritePath:
		$Sprite2D.texture = load(it.spritePath)
	$Sprite2D.frame = it.spriteFrame
	pass
	
@rpc("any_peer", "reliable", "call_local")
func request_pickup(_player_id: int):
	if multiplayer.is_server():
		sync_has_been_picked_up = true
		visible = false
		# Tell all clients to remove the loot
		remove_loot.rpc()
		$SfxPickup.play()
		await $SfxPickup.finished
		# Remove loot on server too
		queue_free()

# Called locally by the player picking up the item
func pick_up_local(player_id: int):
	if sync_has_been_picked_up:
		return
	var player = MultiplayerManager.playersNode.get_node(str(player_id))
	if player:
		sync_has_been_picked_up = true
		visible = false
		# Add item to local inventory
		player.stats.add_item(it)
		# Tell server about pickup
		if not multiplayer.is_server():
			request_pickup.rpc_id(1, player_id)
		else:
			# Tell all clients to remove the loot
			remove_loot.rpc()
		$SfxPickup.play()
		await $SfxPickup.finished
		# Remove loot locally immediately
		queue_free()

@rpc("authority", "reliable")
func remove_loot():
	visible = false
	sync_has_been_picked_up = true
	
	$SfxPickup.play()
	await $SfxPickup.finished
	queue_free()

func _on_area_2d_body_entered(_body: Node2D) -> void:
	$Label.visible = true
	pass # Replace with function body.


func _on_area_2d_body_exited(_body: Node2D) -> void:
	$Label.visible = false
	pass # Replace with function body.


func _on_area_2d_collision_body_entered(_body: Node2D) -> void:
	if bounceTimer == 0:
		#$SfxCoinBounce.play()
		bounceTimer = 0.08
		# inverse the direction and slow down slightly
		var collision_shape = $Area2DCollision.get_overlapping_bodies()
		
		if collision_shape.size() > 0:
			var collider = collision_shape[0]
			var normal = (global_position - collider.global_position).normalized()
			velocity = velocity.bounce(normal)
	
	pass # Replace with function body.


func _on_area_2d_pickup_area_entered(_area: Area2D) -> void:
	$Label.visible = true
	pass # Replace with function body.


func _on_area_2d_pickup_area_exited(_area: Area2D) -> void:
	$Label.visible = false
	pass # Replace with function body.
