extends Node3D

signal camera_changed(camera: Camera3D)

@export_group("Camera")
@export var camera_iso : Camera3D
@export var pivot : Node3D
@export var camera_front : Camera3D
@export var camera_side1 : Camera3D
@export var camera_side2 : Camera3D
@export var camera_top : Camera3D

@export_group("Camera Movememnt")
@export var move_speed : float = 20.0
@export var rotation_speed : float = 0.2

@export_group("Cinematic Mode")
@export var change_camera_time : float = 10.0 

@export_group("Isometric Zoom")
@export var normal_size : float = 35.0
@export var zoom_size : float = 60.0
@export var zoom_time : float = 1.2
var is_zoomed : bool = false
var zoom_tween : Tween

var is_moving_enabled : bool = true

var is_cinematic_mode : bool = false
var cinematic_timer : float = 0.0
var cinematic_index : int = 0
var array_camera : Array[Camera3D] = []

var initial_pivot_transformation : Transform3D

func _ready():
	if pivot:
		initial_pivot_transformation = pivot.transform
		
	if camera_iso: array_camera.append(camera_iso)
	if camera_front: array_camera.append(camera_front)
	if camera_side1: array_camera.append(camera_side1)
	if camera_side2: array_camera.append(camera_side2)
	if camera_top: array_camera.append(camera_top)
	
	if camera_iso:
		set_camera(camera_iso)

func set_camera(camera: Camera3D):
	camera.make_current()
	emit_signal("camera_changed", camera)

func _input(event):
	if event is InputEventKey and event.pressed and not event.echo:
		
		#R-> Reset isometric camera
		if event.keycode == KEY_R and is_moving_enabled and pivot:
			pivot.transform = initial_pivot_transformation
			print("Isometric camera resetted!")
			return 

		#C-> Toggle cinematic mode
		if event.keycode == KEY_C:
			is_cinematic_mode = !is_cinematic_mode
			if is_cinematic_mode:
				cinematic_timer = 0.0 
				for i in range(array_camera.size()):
					if array_camera[i].current:
						cinematic_index = i
						break
				print("Cinematic Mode: enabled")
			else:
				print("Cinematic Mode: disabled")
			return 
			
		#Z-> soft zoom
		if event.keycode == KEY_Z and camera_iso:
			is_zoomed = !is_zoomed
			var target_size = zoom_size if is_zoomed else normal_size
			
			if zoom_tween and zoom_tween.is_valid():
				zoom_tween.kill()
				
			zoom_tween = create_tween()
			zoom_tween.set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
			zoom_tween.tween_property(camera_iso, "size", target_size, zoom_time)
			return

		#manual controls (1-5)
		var manual_action = false
		
		if event.keycode == KEY_1 and camera_iso:
			set_camera(camera_iso)
			is_moving_enabled = true
			manual_action = true
			
		elif event.keycode == KEY_2 and camera_front:
			set_camera(camera_front)
			is_moving_enabled = false
			manual_action = true
			
		elif event.keycode == KEY_3 and camera_side1:
			set_camera(camera_side1)
			is_moving_enabled = false
			manual_action = true
			
		elif event.keycode == KEY_4 and camera_side2:
			set_camera(camera_side2)
			is_moving_enabled = false
			manual_action = true
			
		elif event.keycode == KEY_5 and camera_top:
			set_camera(camera_top)
			is_moving_enabled = false
			manual_action = true
			
		if manual_action and is_cinematic_mode:
			is_cinematic_mode = false
			print("Cinematic Mode: Disabled")

	if is_moving_enabled and pivot:
		if event is InputEventMouseMotion and Input.is_mouse_button_pressed(MOUSE_BUTTON_RIGHT):
			pivot.rotate_y(deg_to_rad(-event.relative.x * rotation_speed))

func _process(delta):
	if is_cinematic_mode and array_camera.size() > 0:
		cinematic_timer += delta
		if cinematic_timer >= change_camera_time:
			cinematic_timer = 0.0
			cinematic_index = (cinematic_index + 1) % array_camera.size()
			var next_cam = array_camera[cinematic_index]
			set_camera(next_cam)
			is_moving_enabled = (next_cam == camera_iso)

	if not is_moving_enabled or pivot == null:
		return
		
	var input_dir = Vector3.ZERO
	if Input.is_key_pressed(KEY_W): input_dir.z -= 1
	if Input.is_key_pressed(KEY_S): input_dir.z += 1
	if Input.is_key_pressed(KEY_A): input_dir.x -= 1
	if Input.is_key_pressed(KEY_D): input_dir.x += 1
	
	if input_dir != Vector3.ZERO:
		input_dir = input_dir.normalized()
		
		var forward = pivot.transform.basis.z
		var right = pivot.transform.basis.x
		forward.y = 0
		right.y = 0
		
		forward = forward.normalized()
		right = right.normalized()
		
		var motion = (forward * input_dir.z + right * input_dir.x)
		pivot.position += motion * move_speed * delta
