extends KinematicBody

signal starved_to_death

const EPSILON = 0.0001
const SPEED = 10.0

export var hunger_tick_time = 30.0
export var inventory = {}

var health: int = 4 setget set_health
var item_in_hand
var move_enabled: bool = true

onready var move_playback = $DungMan/AnimationTree["parameters/Move/playback"]
onready var hunger_timer = $"%hunger_timer"

# Called when the node enters the scene tree for the first time.
func _ready():
	$hitbox.set_meta("owner", self)
	move_playback.travel("idle")
	hunger_timer.wait_time = hunger_tick_time
	hunger_timer.start()

func _physics_process(delta):
	if not move_enabled:
		return
	var input = Vector3(Input.get_axis("left", "right"), 0.0, Input.get_axis("up", "down"))
	var motion = Plane.PLANE_XZ.project(get_viewport().get_camera().global_transform.basis.xform(input)).normalized() * SPEED
	if motion.length_squared() > EPSILON:
		$DungMan.look_at(global_transform.origin - motion, Vector3.UP)
		move_playback.travel("run")
	else:
		move_playback.travel("idle")
	move_and_slide(motion)

func _on_hunger_timer_timeout():
	set_health(health - 1)
	print("player: lost health to hunger tick")

func set_health(new_value):
	health = min(new_value, 4)
	for child in $"%stomachs".get_children():
		child.visible = child.get_index() < health
	if health <= 0:
		emit_signal("starved_to_death")

func can_afford(item_name, item_amount):
	assert(item_amount > 0)
	var current_amount : int = 0
	if(inventory.has(item_name)):
		current_amount = inventory[item_name]
	return current_amount >= item_amount
	
func modify_inventory(item_name, item_amount):
	if item_amount == 0:
		return true
		
	var is_op_valid : bool = true
	
	# Note(asr): check if you can afford the item if we are removing
	# for item grants op is always valid
	if item_amount < 0:
		is_op_valid = can_afford(item_name, abs(item_amount))
		
	if not is_op_valid:
		return false
	
	var current_amount : int = 0
	if inventory.has(item_name):
		current_amount = inventory[item_name]
	# Note(asr): clamp to 0. can't have negative items
	var new_amount : int = max(current_amount + item_amount, 0)
	inventory[item_name] = new_amount
	print("inventory updated: ", item_name, " : ", new_amount)
	return true

func _unhandled_input(event):
	if event.is_action_pressed("action"):
		$DungMan/AnimationTree["parameters/Activate/active"] = true
		move_enabled = false
		yield(get_tree().create_timer(0.2), "timeout")
		for area in $"%TriggerVolume".get_overlapping_areas():
			if try_trigger_interact(area):
				break
		move_enabled = true

func try_trigger_interact(area):
	var owner = area
	if area.has_meta("owner"):
		owner = area.get_meta("owner")
	
	if not owner.has_method("on_player_interact"):
		return false
		
	var result = owner.on_player_interact(self)

	if not result:
		print("player failed to interacted with ", owner)
		return

	print("player interacted with ", owner)
	return true
	
func drop_item_in_hand():
	print("player dropped ", item_in_hand.item_name)
	var item_dropped = item_in_hand
	$"%ItemSpawn".remove_child(item_in_hand)
	item_in_hand = null
	return item_dropped
	
func pick_up_item(item):
	var item_dropped = null
	if item_in_hand != null:
		item_dropped = drop_item_in_hand()
	item_in_hand = item
	$"%ItemSpawn".add_child(item_in_hand)
	print("player picked up ", item_in_hand.item_name)
	return item_dropped

func has_item() -> bool:
	return item_in_hand != null

func get_item_in_hand():
	var item_to_return = null
	if item_in_hand != null:
		item_to_return = drop_item_in_hand()
	return item_to_return


func _on_blink_timer_timeout():
	$DungMan/AnimationTree["parameters/Blink/active"] = true
	$DungMan/blink_timer.wait_time = rand_range(0.5, 3.0)
