extends "res://entities/GridBasedMovable.gd"

enum STATES {IDLE, MOVE}
enum START_DIRS {UP, DOWN, LEFT, RIGHT}

enum _DIRECTIONS {UP, DOWN, LEFT, RIGHT, NONE}

var state = STATES.MOVE
var turned = false
var push_not_blocked #true when able to push or not pushing at all, false when push failed (blocked, unable to move)



var idle_started = true

@export var min_idle_time = 0.2
@export var max_idle_time = 0.2
@export var start_direction: START_DIRS = START_DIRS.UP

@onready var current_direction = start_direction
@onready var idle_timer = $IdleTimer
@export var can_push = false




func _ready() -> void:
	super._ready()
	requested_direction = start_direction
	update_rotation_point(requested_direction)
	push_not_blocked = true
	


func _physics_process(delta: float) -> void:
	move()
	_handle_movement(delta)

func reset_to_idle():
	idle_timer.wait_time = randf_range(min_idle_time, max_idle_time)
	state = STATES.IDLE
	idle_started = true
	idle_timer.start()
	push_not_blocked = true
	
func move():
	var pushable_found = false
	if ray_front.is_colliding() and is_grid_aligned():
		var frontObject = ray_front.get_collider()
		if frontObject != null:
			if frontObject.is_in_group("pushable") and not frontObject.is_in_group("heavy"):
				pushable_found = true
			elif frontObject.get_parent().is_in_group("pushable") and not frontObject.get_parent().is_in_group("heavy"):
				pushable_found = true


	if state == STATES.IDLE:
		if idle_timer.get_time_left() < 0.1 and turned == false:
			update_rotation_point(get_opposite_direction(requested_direction))
			turned = true
			
	if state == STATES.MOVE:

		if ray_front.is_colliding() and is_grid_aligned():
			
			var frontObject = ray_front.get_collider()
			
			if not (pushable_found and can_push == true and push_not_blocked == true):
		

				if idle_timer.get_time_left() == 0 and idle_started == false:
					reset_to_idle()

				else:
					idle_started = false
			

		else:
			requested_direction = current_direction


	
	if ray_ground.is_colliding():
		var groundObject = ray_ground.get_collider()
		if groundObject != null and groundObject.is_in_group("player"):
			groundObject.hit()
			
	var frontObject = ray_front.get_collider()
	if frontObject != null and frontObject.is_in_group("player"):
		frontObject.hit()
	elif frontObject != null and frontObject.get_parent().is_in_group("player"):
		frontObject.get_parent().hit()
			
	if requested_direction != DIRECTIONS.NONE and ray_front.is_colliding() and is_grid_aligned() and can_push == true:
		var local_movedir = direction_to_vector(requested_direction)
		var next_target_pos = position + local_movedir * step_size
		if frontObject != null:
			var _distance = (next_target_pos - frontObject.position).length()
			
			if frontObject.is_in_group("pushable") and not frontObject.is_in_group("heavy"):
				
				push_not_blocked = push(frontObject, requested_direction)
				
				
			elif frontObject.get_parent().is_in_group("pushable") and not frontObject.get_parent().is_in_group("heavy"):
				push_not_blocked = push(frontObject.get_parent(), requested_direction)
				
			
			elif frontObject.is_in_group("heavy") or frontObject.get_parent().is_in_group("heavy"):
					push_not_blocked = true
			else:
				push_not_blocked = true
			
		else:
			print ("error: front raycast hit null object")
		
	if requested_direction == _DIRECTIONS.NONE:
		requested_direction = mesh_direction
	
func change_direction():
	if state == STATES.IDLE:

		
		requested_direction = get_opposite_direction(requested_direction)
		update_rotation_point(requested_direction)
		
		current_direction = requested_direction
		push_not_blocked = true
		
	state = STATES.MOVE
	
		

	




func _on_IdleTimer_timeout() -> void:

	current_direction = get_opposite_direction(requested_direction)
	change_direction()
	
	
	turned = false

func hit():
	call_deferred("queue_free")
