extends Node3D
const MOUSE_MOVE_THRESHOLD = 16
const DEADZONE = 0.2

@onready var pivot_editor = $pivot_editor
@onready var pivot_editor2 = $pivot_editor/pivot_editor2
@onready var lens_editor = $pivot_editor/pivot_editor2/lens
@onready var camera_editor = $camera_editor

@onready var pivot_game = $pivot_game
@onready var pivot_game2 = $pivot_game/pivot_game2
@onready var lens_game = $pivot_game/pivot_game2/lens
@onready var camera_game = $camera_game

var active_pivot = null
var active_pivot2 = null
var active_lens = null
var active_camera = null

@onready var select_plane = $select_plane
@onready var layer_detect = $select_plane/LayerDetect
@onready var level_manager = $"/root/LevelManager"

@export var camera_space_size = 10
@export var rotate_speed = 130
@export var move_speed = 300

var new_position
var navigation_enabled = false

var mouse_drag = false
var mouse_click_position = null
var selected_layer_position = -0.4
var select_box_pos_world = Vector3(0, 0, 0)
var layer_detect_collision_mask
var ray_hit_position = Vector3(0, 0, 0)
var ray_hit = false
var camera_pos_on_drag = Vector3(0, 0, 0)

var relative = Vector2(0, 0)

var camera_angle_y = 0
var _camera_angle_y = 0

var camera_angle_x = 0
var _camera_angle_x = 0

var camera_distance = 0
var _camera_distance = 0



func _ready() -> void:
	
	layer_detect_collision_mask = layer_detect.collision_layer
	


func set_camera_space_size(size):
	camera_space_size = size * 2


func _input(event):
	if !navigation_enabled:
		return
	
	ray_hit = false
	if event is InputEventMouseButton and (event.button_index == MOUSE_BUTTON_LEFT or event.button_index == MOUSE_BUTTON_RIGHT or event.button_index == MOUSE_BUTTON_MIDDLE):
		if event.pressed:
			self.mouse_click_position = event.position
		else:
			self.mouse_click_position = null
	elif event is InputEventMouseMotion:
		if self.mouse_click_position != null:
			if event.position.distance_squared_to(self.mouse_click_position) > self.MOUSE_MOVE_THRESHOLD:
				self.mouse_drag = true
		else:
			self.mouse_drag = false
		
		if self.mouse_drag:
			relative = -event.relative.normalized()
	else:
		relative = Vector2(0, 0)
			
	shoot_ray()


func _process(delta: float) -> void:
	
	if level_manager.editor != null and active_camera == null:
		set_active_camera("editor")
		navigation_enabled = true
		print ("active_camera set to camera_editor")
	elif level_manager.game != null and active_camera == null:
		set_active_camera("game")
		print ("active_camera set to camera_game")

		
	if active_camera == null or !navigation_enabled:
		return


	select_plane.set_position(Vector3(select_plane.position.x, selected_layer_position ,select_plane.position.z))
	new_position = active_pivot.position
	var move_factor = move_speed * delta
	if Input.is_action_pressed("ui_right"):
		new_position += Vector3.RIGHT * move_factor
	if Input.is_action_pressed("ui_left"):
		new_position += Vector3.LEFT * move_factor
	if Input.is_action_pressed("ui_up"):
		new_position += Vector3.FORWARD * move_factor
	if Input.is_action_pressed("ui_down"):
		new_position += Vector3.BACK * move_factor
	if relative and Input.is_action_pressed("ed_camera_move") and !Input.is_action_pressed("ed_camera_rotate"):
		new_position.x -= relative.x * move_factor
		new_position.z -= relative.y * move_factor

	active_pivot.position = lerp(active_pivot.position,new_position,delta*10.0)
	active_pivot.position.x = clamp(active_pivot.position.x, 0, self.camera_space_size)
	active_pivot.position.z = clamp(active_pivot.position.z, 0, self.camera_space_size)

	var axis_value = Vector2()
	
	if relative and Input.is_action_pressed("ed_camera_rotate", true):
		axis_value.x = relative.x
		axis_value.y = relative.y
		active_pivot.position = select_box_pos_world


		
	
	if abs(axis_value.x) > DEADZONE:
		camera_angle_y += self.rotate_speed * axis_value.x * delta
		#camera_angle_y = clamp(camera_angle_y, -90, 90)
		
	if camera_angle_y > 360.0:
		camera_angle_y -= 360.0
	if camera_angle_y < 0.0:
		camera_angle_y += 360.0
	
	if abs(axis_value.y) > DEADZONE:
		camera_angle_x -= self.rotate_speed * axis_value.y * delta
		camera_angle_x = clamp(camera_angle_x, -60, 120)
	
	if camera_angle_y != _camera_angle_y:
		_camera_angle_y = camera_angle_y

		self.active_pivot.set_rotation_degrees(Vector3(0, _camera_angle_y, 0))

	if camera_angle_x != _camera_angle_x:
		_camera_angle_x = camera_angle_x

		self.active_pivot2.set_rotation_degrees(Vector3(_camera_angle_x, 0, 0))


	
	active_camera.global_position = lerp(active_camera.global_position,active_lens.global_position,delta*20.0)
	active_camera.global_rotation = lerp(active_camera.global_rotation,active_lens.global_rotation,delta*20.0)

func shoot_ray():
	var mouse_pos = get_viewport().get_mouse_position()
	var ray_length = 1000
	var from = camera_editor.project_ray_origin(mouse_pos)
	var to = from + camera_editor.project_ray_normal(mouse_pos) * ray_length
	var space = get_world_3d().direct_space_state
	var ray_query = PhysicsRayQueryParameters3D.new()
	ray_query.from = from
	ray_query.to = to
	ray_query.collision_mask = layer_detect_collision_mask
	var raycast_result = space.intersect_ray(ray_query)
	
	if !raycast_result.is_empty():
		ray_hit_position = raycast_result.position
		ray_hit = true
		
func set_active_camera(mode):
	if mode == "editor":
		active_camera = camera_editor
		active_lens = lens_editor
		active_pivot = pivot_editor
		active_pivot2 = pivot_editor2
	elif mode == "game":
		active_camera = camera_game
		active_lens = lens_game
		active_pivot = pivot_game
		active_pivot2 = pivot_game2
	active_camera.current = true
	initialize_active_camera()
	print ("active camera set, initialized")
		
func initialize_active_camera():
	var pivot_rotation = self.active_pivot.get_rotation_degrees()
	camera_angle_y = pivot_rotation.y
	_camera_angle_y = pivot_rotation.y

	pivot_rotation = self.active_pivot2.get_rotation_degrees()
	camera_angle_x = pivot_rotation.x
	_camera_angle_x = pivot_rotation.x

	pivot_rotation = self.active_camera.get_position()
	camera_distance = pivot_rotation.z
	_camera_distance = pivot_rotation.z
	
	active_camera.global_position = active_lens.global_position
	active_camera.global_rotation = active_lens.global_rotation

func snap_camera_position(position, _camera):
	print (position)
	if _camera == "game":
		pivot_game.position = position
	elif _camera == "editor":
		pivot_editor.position = position
	else:
		active_pivot.position = position

func snap_camera_rotation(rotation, _camera):
	if _camera == "game":
		pivot_game2.rotation.x = rotation.x
		pivot_game.rotation.y = rotation.y
	elif _camera == "editor":
		pivot_editor2.rotation.x = rotation.x
		pivot_editor.rotation.y = rotation.y
	else:
		active_pivot2.rotation.x = rotation.x
		active_pivot.rotation.y = rotation.y
		
