# Camera operations module
# Handles: add_camera, set_camera_current, set_camera_properties, get_camera_info
# Corresponds to: test_camera.py
class_name CameraOps


## Add a camera node to a scene
static func add_camera(ctx: SceneTree, params: Dictionary) -> void:
	ctx.log_info("Adding camera: " + params.camera_name)

	var full_scene_path: String = params.scene_path
	if not full_scene_path.begins_with("res://"):
		full_scene_path = "res://" + full_scene_path

	if not FileAccess.file_exists(full_scene_path):
		ctx.log_error("Scene file does not exist: " + full_scene_path)
		ctx.quit(1)

	var scene: PackedScene = load(full_scene_path)
	if not scene:
		ctx.log_error("Failed to load scene: " + full_scene_path)
		ctx.quit(1)

	var scene_root: Node = scene.instantiate()

	# Find parent node
	var parent_node: Node = scene_root.get_node_or_null(NodePath(params.parent_node_path))
	if not parent_node:
		ctx.log_error("Parent node not found: " + params.parent_node_path)
		ctx.quit(1)

	# Create camera
	var camera: Node = ctx.instantiate_class(params.camera_type)
	if not camera:
		ctx.log_error("Failed to create camera of type: " + params.camera_type)
		ctx.quit(1)

	camera.name = params.camera_name

	# Set as current if requested
	if params.get("make_current", true):
		if camera is Camera2D:
			camera.enabled = true
		elif camera is Camera3D:
			camera.current = true

	# Add to scene
	parent_node.add_child(camera)
	camera.owner = scene_root

	if ctx.debug_mode:
		print("[DEBUG] Camera added to scene")

	# Save scene
	var packed_scene: PackedScene = PackedScene.new()
	var result: int = packed_scene.pack(scene_root)

	if result == OK:
		var save_error: int = ResourceSaver.save(packed_scene, full_scene_path)
		if save_error == OK:
			print("Camera '" + params.camera_name + "' added successfully")
		else:
			ctx.log_error("Failed to save scene: " + str(save_error))
			ctx.quit(1)
	else:
		ctx.log_error("Failed to pack scene: " + str(result))
		ctx.quit(1)


## Set a camera as current
static func set_camera_current(ctx: SceneTree, params: Dictionary) -> void:
	ctx.log_info("Setting current camera")

	var full_scene_path: String = params.scene_path
	if not full_scene_path.begins_with("res://"):
		full_scene_path = "res://" + full_scene_path

	if not FileAccess.file_exists(full_scene_path):
		ctx.log_error("Scene file does not exist: " + full_scene_path)
		ctx.quit(1)

	var scene: PackedScene = load(full_scene_path)
	if not scene:
		ctx.log_error("Failed to load scene: " + full_scene_path)
		ctx.quit(1)

	var scene_root: Node = scene.instantiate()

	# Find camera node
	var camera: Node = scene_root.get_node_or_null(NodePath(params.camera_path))
	if not camera:
		ctx.log_error("Camera node not found: " + params.camera_path)
		ctx.quit(1)

	# Set as current
	if camera is Camera2D:
		camera.enabled = true
	elif camera is Camera3D:
		camera.current = true
	else:
		ctx.log_error("Node is not a Camera2D or Camera3D: " + params.camera_path)
		ctx.quit(1)

	# Save scene
	var packed_scene: PackedScene = PackedScene.new()
	var result: int = packed_scene.pack(scene_root)

	if result == OK:
		var save_error: int = ResourceSaver.save(packed_scene, full_scene_path)
		if save_error == OK:
			print("Camera set as current")
		else:
			ctx.log_error("Failed to save scene: " + str(save_error))
			ctx.quit(1)
	else:
		ctx.log_error("Failed to pack scene: " + str(result))
		ctx.quit(1)


## Set camera properties
static func set_camera_properties(ctx: SceneTree, params: Dictionary) -> void:
	ctx.log_info("Setting camera properties")

	var full_scene_path: String = params.scene_path
	if not full_scene_path.begins_with("res://"):
		full_scene_path = "res://" + full_scene_path

	if not FileAccess.file_exists(full_scene_path):
		ctx.log_error("Scene file does not exist: " + full_scene_path)
		ctx.quit(1)

	var scene: PackedScene = load(full_scene_path)
	if not scene:
		ctx.log_error("Failed to load scene: " + full_scene_path)
		ctx.quit(1)

	var scene_root: Node = scene.instantiate()

	# Find camera node
	var camera: Node = scene_root.get_node_or_null(NodePath(params.camera_path))
	if not camera:
		ctx.log_error("Camera node not found: " + params.camera_path)
		ctx.quit(1)

	# Set properties based on camera type
	if camera is Camera2D:
		if params.has("zoom"):
			var zoom_data = _parse_vector2(params.zoom)
			if zoom_data:
				camera.zoom = zoom_data
		if params.has("offset"):
			var offset_data = _parse_vector2(params.offset)
			if offset_data:
				camera.offset = offset_data
	elif camera is Camera3D:
		if params.has("fov"):
			camera.fov = params.fov
		if params.has("near"):
			camera.near = params.near
		if params.has("far"):
			camera.far = params.far
		if params.has("offset"):
			var offset_data = _parse_vector3(params.offset)
			if offset_data:
				camera.position = offset_data
	else:
		ctx.log_error("Node is not a Camera2D or Camera3D: " + params.camera_path)
		ctx.quit(1)

	if ctx.debug_mode:
		print("[DEBUG] Camera properties set")

	# Save scene
	var packed_scene: PackedScene = PackedScene.new()
	var result: int = packed_scene.pack(scene_root)

	if result == OK:
		var save_error: int = ResourceSaver.save(packed_scene, full_scene_path)
		if save_error == OK:
			print("Camera properties updated")
		else:
			ctx.log_error("Failed to save scene: " + str(save_error))
			ctx.quit(1)
	else:
		ctx.log_error("Failed to pack scene: " + str(result))
		ctx.quit(1)


## Get camera information
static func get_camera_info(ctx: SceneTree, params: Dictionary) -> void:
	var full_scene_path: String = params.scene_path
	if not full_scene_path.begins_with("res://"):
		full_scene_path = "res://" + full_scene_path

	if not FileAccess.file_exists(full_scene_path):
		ctx.log_error("Scene file does not exist: " + full_scene_path)
		ctx.quit(1)

	var scene: PackedScene = load(full_scene_path)
	if not scene:
		ctx.log_error("Failed to load scene: " + full_scene_path)
		ctx.quit(1)

	var scene_root: Node = scene.instantiate()

	# Find camera node
	var camera: Node = scene_root.get_node_or_null(NodePath(params.camera_path))
	if not camera:
		ctx.log_error("Camera node not found: " + params.camera_path)
		ctx.quit(1)

	var info: Dictionary = {
		"name": camera.name,
		"type": camera.get_class(),
	}

	if camera is Camera2D:
		info["is_current"] = camera.enabled
		info["zoom"] = [camera.zoom.x, camera.zoom.y]
		info["offset"] = [camera.offset.x, camera.offset.y]
	elif camera is Camera3D:
		info["is_current"] = camera.current
		info["fov"] = camera.fov
		info["near"] = camera.near
		info["far"] = camera.far
	else:
		ctx.log_error("Node is not a Camera2D or Camera3D: " + params.camera_path)
		ctx.quit(1)

	print(JSON.stringify(info, "\t"))


# Helper functions

static func _parse_vector2(data) -> Vector2:
	if typeof(data) == TYPE_STRING:
		var json: JSON = JSON.new()
		if json.parse(data) == OK:
			var arr: Array = json.get_data()
			if arr.size() >= 2:
				return Vector2(arr[0], arr[1])
	elif typeof(data) == TYPE_ARRAY and data.size() >= 2:
		return Vector2(data[0], data[1])
	return Vector2.ZERO


static func _parse_vector3(data) -> Vector3:
	if typeof(data) == TYPE_STRING:
		var json: JSON = JSON.new()
		if json.parse(data) == OK:
			var arr: Array = json.get_data()
			if arr.size() >= 3:
				return Vector3(arr[0], arr[1], arr[2])
	elif typeof(data) == TYPE_ARRAY and data.size() >= 3:
		return Vector3(data[0], data[1], data[2])
	return Vector3.ZERO
