extends Actor

export var player_number: int = 1


onready var player_inventory :InventoryManager = InventoryManager.new()
onready var stamina_component = $"%Stamina_Component"
onready var health_component = $"%Health_Component"
onready var hitbox_component = $Hitbox_Component
onready var hurtbox_component = $Hurtbox_Component



const state_stamina_cost :Dictionary = {
	"jump": 10,
	"attack_sword":20,
	"attack_punch":10,
	#"roll":40,
	"roll":4,
	"ledge_climb":10
}

const state_damage_amount :Dictionary = {
	"attack_sword":30,
	"attack_punch":10,
}

const state_to_item_map :Dictionary = {
	"sword": "attack_sword" ,
	"gun": "attack_shoot",
	"punch" : "attack_punch", 
	"mushroom" : "attack_shoot"
}

var player_info_index :int
var player_data :PlayerData

## Temp Modifier to test movement modifier (getting tired)
var tired_debuff_modifier = StateModifierMovement.new()
#	attack_sword = StateModifierAnimatedActor.new()
#	attack_sword.setup('sword_drawn',StateModifier.TYPE.ANIMATION_SUFFIX,2.0)
#	add_child(attack_sword.timeout)
#	#attack_sword.animation_name = 'PoopenStein'
#	attack_sword.animation_suffix = 'attack-sword'
#	add_state_modifier.call_func(attack_sword)


# Called when the node enters the scene tree for the first time.
func _ready():
	# I think we only want to do this for network master players now
	if is_network_master():
		player_info_index = PlayerInfo.register_player()
		if debug_actor:
			print ("Registered as player: ", player_info_index)
		player_data = PlayerInfo.get_player_data(player_info_index)
		PlayerInfo.get_player_data(player_info_index).player_health = health_component.health
		player_data.player_inventory = player_inventory
		player_data.player_stamina = stamina_component.stamina
	else:
		## puppets cannot get hurt, only network master.
		hurtbox_component.hurtbox_entered_function = ''

	# Set initial player position in world.
	global_position = LevelInfo.player_start_position

	## Give player punch ability at start.
	var punch_item :Item = preload("res://assets/items/punch.tres")
	player_inventory.add_to_inventory(punch_item)
	player_inventory.select_primary(punch_item)
	
	movement_component.state_stamina_cost = state_stamina_cost
	
	tired_debuff_modifier.setup('so_tired', StateModifierMovement.SUB_TYPE.NEGATIVE_CONSTRAINT)
	tired_debuff_modifier.speed_start = Vector2(-40,0)
	tired_debuff_modifier.processing_mode = StateModifierMovement.SUB_TYPE.NEGATIVE_CONSTRAINT
	#tired_debuff_modifier.horizontal_speed = -40
	tired_debuff_modifier.only_grounded = true
	movement_state_machine.push_state_modifier(tired_debuff_modifier)

#var stamina_recovery :float = 0.0

# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
	if is_network_master():
		## Update position and stamina in player data 
		player_data.player_position = global_position.round()
		player_data.player_stamina = stamina_component.stamina
		
		match movement_state_machine.current_state.name:
			"idle":
				if Input.is_action_just_released("switch_primary_item_" + str(player_number)):
					var _selected_item = player_inventory.switch_primary()
					if _selected_item:
						print("Switched Primary item to: ", _selected_item.name)
				elif Input.is_action_just_released("switch_secondary_item_" + str(player_number)):
					var _selected_item = player_inventory.switch_secondary()
					if _selected_item:
						print("Switched Secondary item to: ", _selected_item.name)

	# Adjust hitbox damage to current states or default
	##TODO: well I'm not sure I like this but making a whole state receiver is silly
	if state_damage_amount.has(movement_state_machine.current_state.name):
		hitbox_component.damage_amount = state_damage_amount[movement_state_machine.current_state.name]
	else:
		hitbox_component.damage_amount = 10
	
	if stamina_component.stamina < 20 and tired_debuff_modifier.is_active == false:
		tired_debuff_modifier.activate()
	if stamina_component.stamina > 20 and tired_debuff_modifier.is_active == true:
		tired_debuff_modifier.deactivate()


func hit_Receiver(damage):
	hurtbox_component.set_hurtbox(false)
	health_component.take_damage(damage)
	if health_component.health > 0:
		movement_state_machine.change_to_known_state('hurt')
	#PlayerInfo.player_health = health_component.health
	player_data.player_health = health_component.health
	print ("Got Hurt, What happend: " , PlayerInfo.get_player_data(player_info_index).player_health, " vs ", player_data.player_health)
	if health_component.health <= 0:
		return
	yield( get_tree().create_timer(2 + movement_state_machine.get_state_reference('hurt').timeout_seconds), "timeout")
	hurtbox_component.set_hurtbox(true)

## Interactable Receiver callback function. Anything touched goes here.
func touch_the_thing(the_thing: Interactable) -> bool:
	print("You see! a THING...", the_thing.name)
	if the_thing is HealthPickup:
		# Do some healthy stuff.
		the_thing.trigger_interaction()
		return false
	if the_thing is LevelTransition:
		if movement_state_machine.current_state.name != 'enter_right':
			if the_thing._transition_type == 'door_right':
				# Make sure we're facing right.
				transform.x.x = movement_component.RIGHT
				movement_state_machine.change_to_known_state('enter_right')
			elif the_thing._transition_type == 'door_left':
				transform.x.x = movement_component.LEFT
				movement_state_machine.change_to_known_state('enter_right')
			the_thing.trigger_interaction()
	if the_thing is ItemPickup:
		player_inventory.add_to_inventory(the_thing.item, the_thing.count)
		#player_inventory.select_secondary(the_thing.item)
		the_thing.trigger_interaction()
	return true


func enough_stamina_for(_state_name :String) -> bool:
	if state_stamina_cost.has(_state_name):
		if stamina_component.stamina >= state_stamina_cost[_state_name]:
			return true
		else: 
			return false
	## Return true by default because we don't have a cost for this move
	return true

##DONE: We need to find a way to 'use' the item.
func use_primary_item() -> String:
	if player_inventory.primary_selection != null: # Have to make sure we even have a second
		var _item_name :String = player_inventory.primary_selection.name
		if state_to_item_map.has(_item_name):
			var state_name = state_to_item_map[_item_name]
			## This item state has a cost associated with it.
			if enough_stamina_for(state_name):
				#print("Yup: ", state_stamina_cost[state_name], "<=", stamina_component.stamina)
				player_inventory.remove_from_inventory(player_inventory.primary_selection)
				return state_to_item_map[_item_name]
			else:
				##TODO: maybe some sort of 'fail' animation state
				#print("Nope: ", state_stamina_cost[state_name], "<=", stamina_component.stamina)
				return '' ## you can't use this
			## use item even if no stamina usage needed for it.
			player_inventory.remove_from_inventory(player_inventory.primary_selection)
			return state_to_item_map[_item_name]

	return ''

func use_secondary_item() -> String:
	if player_inventory.secondary_selection != null: # Have to make sure we even have a second
		var _item_name :String = player_inventory.secondary_selection.name
		if state_to_item_map.has(_item_name):
			var state_name = state_to_item_map[_item_name]
			if enough_stamina_for(state_name):
				player_inventory.remove_from_inventory(player_inventory.secondary_selection)
				return state_to_item_map[_item_name]
			else:
				## TODO: maybe some sort of 'fail' animation state
				return ''
			## use item even if no stamina usage needed for it.
			player_inventory.remove_from_inventory(player_inventory.secondary_selection)
			return state_to_item_map[_item_name]

	return ''


func _on_Movement_StateMachine_state_changed(old_state_name, new_state):
	## Reduce stamina if this state has a cost
	if state_stamina_cost.has(new_state.name):
		stamina_component.reduce_stamina(state_stamina_cost[new_state.name])


func _on_Health_Component_health_depleted():
	movement_state_machine.change_to_known_state('death')
	NetworkManager.end_game()
