# Particle operations module
# Handles: add_particle_system, set_particle_properties, start_particle_emitting
# Corresponds to: test_particle.py
class_name ParticleOps


## Add a particle system to a scene
static func add_particle_system(ctx: SceneTree, params: Dictionary) -> void:
	ctx.log_info("Adding particle system: " + params.particle_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 particle system
	var particles: Node = ctx.instantiate_class(params.particle_type)
	if not particles:
		ctx.log_error("Failed to create particle system of type: " + params.particle_type)
		ctx.quit(1)

	particles.name = params.particle_name

	# Set basic properties
	if particles is CPUParticles2D or particles is CPUParticles3D:
		particles.amount = params.get("amount", 8)
		particles.emitting = params.get("emitting", true)
	elif particles is GPUParticles2D or particles is GPUParticles3D:
		particles.amount = params.get("amount", 8)
		particles.emitting = params.get("emitting", true)

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

	if ctx.debug_mode:
		print("[DEBUG] Particle system 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("Particle system '" + params.particle_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 particle system properties
static func set_particle_properties(ctx: SceneTree, params: Dictionary) -> void:
	ctx.log_info("Setting particle 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 particle system
	var particles: Node = scene_root.get_node_or_null(NodePath(params.particle_path))
	if not particles:
		ctx.log_error("Particle system not found: " + params.particle_path)
		ctx.quit(1)

	# Check if it's a particle system
	var is_cpu_2d: bool = particles is CPUParticles2D
	var is_cpu_3d: bool = particles is CPUParticles3D
	var is_gpu_2d: bool = particles is GPUParticles2D
	var is_gpu_3d: bool = particles is GPUParticles3D

	if not (is_cpu_2d or is_cpu_3d or is_gpu_2d or is_gpu_3d):
		ctx.log_error("Node is not a particle system: " + params.particle_path)
		ctx.quit(1)

	# Set CPU Particles properties
	if is_cpu_2d or is_cpu_3d:
		if params.has("lifetime"):
			particles.lifetime = params.lifetime
		if params.has("speed_scale"):
			particles.speed_scale = params.speed_scale
		if params.has("explosiveness"):
			particles.explosiveness_ratio = params.explosiveness
		if params.has("randomness"):
			particles.randomness_ratio = params.randomness

		if params.has("direction"):
			var dir = _parse_vector(params.direction, is_cpu_3d)
			if dir:
				if is_cpu_2d:
					particles.direction = dir as Vector2
				else:
					particles.direction = dir as Vector3

		if params.has("spread"):
			particles.spread = params.spread

		if params.has("gravity"):
			var grav = _parse_vector(params.gravity, is_cpu_3d)
			if grav:
				if is_cpu_2d:
					particles.gravity = grav as Vector2
				else:
					particles.gravity = grav as Vector3

		if params.has("initial_velocity_min"):
			particles.initial_velocity_min = params.initial_velocity_min
		if params.has("initial_velocity_max"):
			particles.initial_velocity_max = params.initial_velocity_max

	# Set GPU Particles properties
	elif is_gpu_2d or is_gpu_3d:
		if params.has("lifetime"):
			particles.lifetime = params.lifetime
		if params.has("speed_scale"):
			particles.speed_scale = params.speed_scale
		if params.has("explosiveness"):
			particles.explosiveness = params.explosiveness
		if params.has("randomness"):
			particles.randomness = params.randomness

	if ctx.debug_mode:
		print("[DEBUG] Particle 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("Particle 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)


## Start/stop particle emission
static func start_particle_emitting(ctx: SceneTree, params: Dictionary) -> void:
	ctx.log_info("Setting particle emission state")

	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 particle system
	var particles: Node = scene_root.get_node_or_null(NodePath(params.particle_path))
	if not particles:
		ctx.log_error("Particle system not found: " + params.particle_path)
		ctx.quit(1)

	# Set emitting state
	if particles is CPUParticles2D or particles is CPUParticles3D or \
	   particles is GPUParticles2D or particles is GPUParticles3D:
		particles.emitting = params.get("emitting", true)
	else:
		ctx.log_error("Node is not a particle system: " + params.particle_path)
		ctx.quit(1)

	if ctx.debug_mode:
		print("[DEBUG] Particle emission state 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("Particle emission state 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)


# Helper function

static func _parse_vector(data, is_3d: bool):
	if typeof(data) == TYPE_STRING:
		var json: JSON = JSON.new()
		if json.parse(data) == OK:
			var arr: Array = json.get_data()
			if is_3d and arr.size() >= 3:
				return Vector3(arr[0], arr[1], arr[2])
			elif not is_3d and arr.size() >= 2:
				return Vector2(arr[0], arr[1])
	elif typeof(data) == TYPE_ARRAY:
		if is_3d and data.size() >= 3:
			return Vector3(data[0], data[1], data[2])
		elif not is_3d and data.size() >= 2:
			return Vector2(data[0], data[1])
	return null
