class_name Player extends CharacterBody2D

@onready var locomotion_comp: LocomotionComponent = %LocomotionComponent
@onready var hsm: LimboHSM = %PlayerHSM
@onready var wall_detector: WallDetector = %WallDetector
@onready var hit_box: Area2D = %HitBox
@onready var spawn_hook_comp: SpawnHookComponet = $SpawnHookComponet

@onready var foot_pos_marker: Marker2D = %FootPosMarker
@onready var ground_companion: Area2D = %GroundCompanion


enum Direction{LEFT,RIGHT}
var direction: Direction = Direction.RIGHT: set = _player_direction_changed

var m_jump_press: bool = false
var m_dash_press: bool = false
var m_climb_press: bool = false
var m_grap_hook_press: bool = false

##用于记录当前玩家输入的朝向
var m_input_intent_direction: Vector2

var is_dead: bool = false:
	set(value):
		is_dead = value
		if is_dead:
			locomotion_comp.is_active = false
			GlobalEvent.boradcast_player_dead_event(self)
			player_dead.emit()

signal player_direction_changed(direction: Direction)
signal player_dead

##落地尘土特效
signal v_land_dust
##奔跑尘土特效
signal v_run_dust
##跳跃尘土特效
signal v_jump_dust

##跳跃声音特效
signal s_jump_sound

func _enter_tree() -> void:
	GlobalEvent.register_player(self)

func _ready() -> void:
	self.player_direction_changed.connect(_handle_direction_changed)
	self.hit_box.area_entered.connect(_handle_hit_box_entered)
	self.hit_box.body_entered.connect(_handle_hit_box_entered)

func _draw() -> void:
	draw_string(ThemeDB.fallback_font,Vector2.ZERO,str(get_wall_normal()))
	
	var x: float = clampf(abs(velocity.x),1,1000) * .2 * sign(velocity.x)
	var y: float = clampf(abs(velocity.y),1,1000) * .2 * sign(velocity.y)
	
	draw_line(Vector2.ZERO,Vector2(x, 0),Color.RED,4)
	draw_line(Vector2.ZERO,Vector2(0, y),Color.GREEN,4)

func _process(delta: float) -> void:
	queue_redraw()


func set_move_input(dir: Vector2) -> void:
	m_input_intent_direction = dir

func get_move_input() -> Vector2:
	return m_input_intent_direction

## 更宽泛的floor检测
func get_is_on_floor() -> bool:
	return self.is_on_floor() or ground_companion.has_overlapping_areas() or ground_companion.has_overlapping_bodies()

#region 输入处理
'''对于单次的输入触发动作，我们发送一个格式为
		want_to_...的事件给hsm，用来尝试触发
'''

func press_jump() -> void:
	m_jump_press = true
	hsm.dispatch(&"trigger_jump")

func release_jump() -> void:
	m_jump_press = false
	hsm.dispatch(&"completed_jump")

func press_dash() -> void:
	m_dash_press = true
	hsm.dispatch(&"trigger_dash")

func release_dash() -> void:
	m_dash_press = false
	hsm.dispatch(&"completed_dash")

func press_climb() -> void:
	m_climb_press = true
	hsm.dispatch(&"trigger_climb")

func release_climb() -> void:
	m_climb_press = false
	hsm.dispatch(&"completed_climb")

func press_grap_hook() -> void:
	m_grap_hook_press = true
	hsm.dispatch(&"trigger_grap_hook")

func release_grap_hook() -> void:
	m_grap_hook_press = true
	hsm.dispatch(&"completed_grap_hook")
#endregion

##玩家方向改变时更新
func _handle_direction_changed(value: Direction):
	match value:
		Direction.RIGHT:
			wall_detector.flip_h = false
		Direction.LEFT:
			wall_detector.flip_h = true

func _handle_hit_box_entered(node: Node2D)-> void:
	hsm.dispatch(&"try_enter_dead")

func _player_direction_changed(value: Direction):
	if self.direction == value:
		return
	direction = value
	player_direction_changed.emit(direction)

func is_in_ground_state() -> bool:
	return %Grounded.is_active()

func is_in_climb_state() -> bool:
	return %Climb.is_active()

#region 特效广播
##播放落地尘土特效
func on_land_dust() -> void:
	v_land_dust.emit({"world_pos": foot_pos_marker.global_position})

##播放落地尘土特效
func on_run_dust() -> void:
	v_run_dust.emit({"world_pos": foot_pos_marker.global_position})

##播放落地尘土特效
func on_jump() -> void:
	v_jump_dust.emit({"world_pos": foot_pos_marker.global_position})
	s_jump_sound.emit()
#endregion


##工具函数
##获取当前state下的目标state
func _get_target_state_in_state(state : LimboState,target: LimboState) -> LimboState:
	if state == target:
		return target
	
	var active_substate : LimboState = null

	# 如果这个状态有 get_active_state() 方法，就调用
	if state.has_method("get_active_state"):
		active_substate = state.get_active_state()
	
	if active_substate == target:
		return target

	# 如果没有子状态，返回自己
	if active_substate == null:
		return null

	# 如果有子状态，继续递归
	return _get_target_state_in_state(active_substate,target)

static func get_direction_vector(dir: Direction) -> Vector2:
	return Vector2(1,0) if dir == Direction.RIGHT else Vector2(-1,0)
