# Light operations module
# Handles: add_light, set_light_properties, set_light_shadow, setup_environment
# Corresponds to: test_light.py
class_name LightOps


## Add a light source to a 3D scene
static func add_light(ctx: SceneTree, params: Dictionary) -> void:
	ctx.log_info("Adding light: " + params.light_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)

	# Validate and normalize light type
	var valid_light_types: Array = ["DirectionalLight3D", "OmniLight3D", "SpotLight3D"]
	var light_type: String = params.light_type

	# Map deprecated PointLight3D to OmniLight3D
	if light_type == "PointLight3D":
		light_type = "OmniLight3D"
		ctx.log_info("PointLight3D is deprecated, using OmniLight3D instead")

	if not light_type in valid_light_types:
		ctx.log_error("Invalid light type: " + params.light_type + ". Valid types: " + str(valid_light_types))
		ctx.quit(1)

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

	light.name = params.light_name

	# Set basic properties
	if light is Light3D:
		light.light_energy = params.get("energy", 1.0)

		# Parse color
		var color_data = _parse_color(params.get("color", "[1, 1, 1]"))
		if color_data:
			light.light_color = color_data

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

	if ctx.debug_mode:
		print("[DEBUG] Light 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("Light '" + params.light_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 light properties
static func set_light_properties(ctx: SceneTree, params: Dictionary) -> void:
	ctx.log_info("Setting light 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 light
	var light: Node = scene_root.get_node_or_null(NodePath(params.light_path))
	if not light:
		ctx.log_error("Light not found: " + params.light_path)
		ctx.quit(1)

	if not light is Light3D:
		ctx.log_error("Node is not a Light3D: " + params.light_path)
		ctx.quit(1)

	# Set properties
	if params.has("energy"):
		light.light_energy = params.energy

	if params.has("color"):
		var color_data = _parse_color(params.color)
		if color_data:
			light.light_color = color_data

	# Properties for OmniLight3D and SpotLight3D
	if light is OmniLight3D:
		if params.has("range"):
			light.omni_range = params.range
		if params.has("attenuation"):
			light.omni_attenuation = params.attenuation
	elif light is SpotLight3D:
		if params.has("range"):
			light.spot_range = params.range
		if params.has("attenuation"):
			light.spot_attenuation = params.attenuation

	# Properties specific to SpotLight3D
	if light is SpotLight3D:
		if params.has("spot_angle"):
			light.spot_angle = params.spot_angle

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


## Set light shadow properties
static func set_light_shadow(ctx: SceneTree, params: Dictionary) -> void:
	ctx.log_info("Setting light shadow 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 light
	var light: Node = scene_root.get_node_or_null(NodePath(params.light_path))
	if not light:
		ctx.log_error("Light not found: " + params.light_path)
		ctx.quit(1)

	if not light is Light3D:
		ctx.log_error("Node is not a Light3D: " + params.light_path)
		ctx.quit(1)

	# Set shadow properties
	light.shadow_enabled = params.get("shadow_enabled", true)

	if params.has("shadow_bias"):
		light.shadow_bias = params.shadow_bias
	if params.has("shadow_blur"):
		light.shadow_blur = params.shadow_blur

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


## Setup environment for a 3D scene
static func setup_environment(ctx: SceneTree, params: Dictionary) -> void:
	ctx.log_info("Setting up environment")

	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 WorldEnvironment
	var world_env: WorldEnvironment = WorldEnvironment.new()
	world_env.name = params.get("environment_name", "WorldEnvironment")

	# Create Environment resource
	var environment: Environment = Environment.new()

	# Set ambient light
	if params.has("ambient_light_color"):
		var color_data = _parse_color(params.ambient_light_color)
		if color_data:
			environment.ambient_light_color = color_data

	if params.has("ambient_light_energy"):
		environment.ambient_light_energy = params.ambient_light_energy

	# Set background
	var bg_mode: String = params.get("background_mode", "Sky")
	match bg_mode.to_upper():
		"SKY":
			environment.background_mode = Environment.BG_SKY
		"COLOR":
			environment.background_mode = Environment.BG_COLOR
			if params.has("sky_color"):
				var color_data = _parse_color(params.sky_color)
				if color_data:
					environment.background_color = color_data
		"CUSTOM":
			environment.background_mode = Environment.BG_CANVAS

	world_env.environment = environment

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

	if ctx.debug_mode:
		print("[DEBUG] Environment setup complete")

	# 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("Environment setup complete")
		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_color(data) -> Color:
	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 Color(arr[0], arr[1], arr[2])
	elif typeof(data) == TYPE_ARRAY and data.size() >= 3:
		return Color(data[0], data[1], data[2])
	return Color.WHITE
