extends RigidBody3D
var rot_x = 0
var rot_y = 0

@onready var world = preload("res://world.tscn")

@export var PLAYER_SPEED = 1.0
@export var PLAYER_REACH = 1000
@export var NOCLIP = false
@export_range(0.00001, 0.01) var LOOK_SENSITIVITY = 0.002
var move_x = 0
var move_y = 0
var move_z = 0
var camera: Camera3D 
var ray_hit_positions = []
var delta_speed = 0
# Declare member variables here. Examples:
# var a = 2
# var b = "text"


# Called when the node enters the scene tree for the first time.
func _ready():
	Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
	camera = find_child("PlayerCamera")
	pass # Replace with function body.


func _input(event):
	if Input.is_action_just_pressed("LeftClick"):
		raycast_from_center()
	
	if Input.is_action_just_pressed("RightClick"):
		pass
	
	if event is InputEventKey and event.is_action_released("ShowCursor"):
		if Input.mouse_mode == Input.MOUSE_MODE_VISIBLE:
			Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
		else:
			Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
			
	if event is InputEventMouseMotion and (Input.mouse_mode == Input.MOUSE_MODE_CAPTURED or event.button_mask & 1):
		# modify accumulated mouse rotation
		rot_x += event.relative.x * LOOK_SENSITIVITY
		rot_y += event.relative.y * LOOK_SENSITIVITY
		camera.transform.basis = Basis() # reset rotation
		rot_x = fmod(rot_x, (PI * 2))
		rot_y = fmod(rot_y, (PI * 2))
		camera.rotate_object_local(Vector3(0, -1, 0), rot_x) # first rotate in Y
		camera.rotate_object_local(Vector3(-1, 0, 0), rot_y) # then rotate in X
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(_delta):
	delta_speed = PLAYER_SPEED * _delta * 500
	if NOCLIP:
		process_noclip()
	else:
		process_physics_movements()
	
	#for hit_pos in ray_hit_positions:
		#DebugDraw3D.draw_sphere(hit_pos)
	
	

func process_physics_movements():
	if Input.is_action_pressed("MoveCamUp"):
		move_y = 1
	if Input.is_action_pressed("MoveCamDown"):
		pass
	if Input.is_action_pressed("MoveCamLeft"):
		move_x = -1
	if Input.is_action_pressed("MoveCamRight"):
		move_x = 1
	if Input.is_action_pressed("MoveCamForward"):
		move_z = 1
	if Input.is_action_pressed("MoveCamBack"):
		move_z = -1
	
	constant_force.y = move_y * delta_speed
	constant_force.x = (sin(rot_x) * move_z * delta_speed + cos(rot_x) * move_x * delta_speed)
	constant_force.z = (-cos(rot_x) * move_z * delta_speed + sin(rot_x) * move_x * delta_speed)
	
	if constant_force.x != 0 || constant_force.y != 0 || constant_force.z != 0:
		physics_material_override.friction = 0
	else:
		physics_material_override.friction = 1
	
	move_y = 0
	move_x = 0
	move_z = 0
		

func raycast_from_center():
	var center = get_viewport().size / 2
	var ray_length = PLAYER_REACH
	var ray_origin = camera.project_ray_origin(center)
	var ray_direction = ray_origin + camera.project_ray_normal(center) * ray_length
	var space = get_world_3d().direct_space_state
	var ray_query = PhysicsRayQueryParameters3D.new()
	ray_query.from = ray_origin
	ray_query.to = ray_direction
	ray_query.exclude = [self]
	var raycast_result = space.intersect_ray(ray_query)
	
	if len(raycast_result) > 0:
		var hit_pos = raycast_result.position - (raycast_result.normal * 0.5)
		hit_pos = Vector3i(round(hit_pos.x), round(hit_pos.y), round(hit_pos.z))
		ray_hit_positions.append(hit_pos)
		world.SetBlockAtPosition(hit_pos, Block.BlockType.Air)
		
		


func process_noclip():
	if Input.is_action_pressed("MoveCamUp"):
		move_y = 1
	if Input.is_action_pressed("MoveCamDown"):
		move_y = -1
	if Input.is_action_pressed("MoveCamLeft"):
		move_x = -1
	if Input.is_action_pressed("MoveCamRight"):
		move_x = 1
	if Input.is_action_pressed("MoveCamForward"):
		move_z = 1
	if Input.is_action_pressed("MoveCamBack"):
		move_z = -1
	
	position.y += move_y * delta_speed
	position.x += (sin(rot_x) * move_z * delta_speed + cos(rot_x) * move_x * delta_speed)
	position.z += (-cos(rot_x) * move_z * delta_speed + sin(rot_x) * move_x * delta_speed)
	
	move_y = 0
	move_x = 0
	move_z = 0
