-- Copyright (c) 2012-2025 Daniele Bartolini et al.
-- SPDX-License-Identifier: MIT

require "core/lua/class"

SoundObject = class(SoundObject)

function SoundObject:init(world, id, name, range, volume, loop)
	self._world = world
	self._id = id
	self._name = name
	self._range = range
	self._volume = volume
	self._loop = loop
	self._unit_id = World.spawn_unit(world, "core/units/sound")
	self._sg = World.scene_graph(world)
	self._selected = false
end

function SoundObject:id()
	return self._id
end

function SoundObject:unit_id()
	return self._unit_id
end

function SoundObject:destroy()
	UnitUtils.destroy_tree(self._world, self._unit_id)
end

function SoundObject:name()
	return self._name
end

function SoundObject:is_spatial()
	return true
end

function SoundObject:local_position()
	local tr = SceneGraph.instance(self._sg, self._unit_id)
	return tr and SceneGraph.local_position(self._sg, tr) or Vector3.zero()
end

function SoundObject:local_rotation()
	local tr = SceneGraph.instance(self._sg, self._unit_id)
	return tr and SceneGraph.local_rotation(self._sg, tr) or Quaternion.identity()
end

function SoundObject:local_scale()
	local tr = SceneGraph.instance(self._sg, self._unit_id)
	return tr and SceneGraph.local_scale(self._sg, tr) or Vector3(1, 1, 1)
end

function SoundObject:local_pose()
	local tr = SceneGraph.instance(self._sg, self._unit_id)
	return tr and SceneGraph.local_pose(self._sg, tr) or Matrix4x4.identity()
end

function SoundObject:world_position()
	local tr = SceneGraph.instance(self._sg, self._unit_id)
	return tr and SceneGraph.world_position(self._sg, tr) or Vector3.zero()
end

function SoundObject:world_rotation()
	local tr = SceneGraph.instance(self._sg, self._unit_id)
	return tr and SceneGraph.world_rotation(self._sg, tr) or Quaternion.identity()
end

function SoundObject:world_scale()
	return Vector3(1, 1, 1)
end

function SoundObject:world_pose()
	local tr = SceneGraph.instance(self._sg, self._unit_id)
	return tr and SceneGraph.world_pose(self._sg, tr) or Matrix4x4.identity()
end

function SoundObject:set_local_position(pos)
	local tr = SceneGraph.instance(self._sg, self._unit_id)
	if tr then SceneGraph.set_local_position(self._sg, tr, pos) end
end

function SoundObject:set_local_rotation(rot)
	local tr = SceneGraph.instance(self._sg, self._unit_id)
	if tr then SceneGraph.set_local_rotation(self._sg, tr, rot) end
end

function SoundObject:set_local_scale(scale)
	local tr = SceneGraph.instance(self._sg, self._unit_id)
	if tr then SceneGraph.set_local_scale(self._sg, tr, scale) end
end

function SoundObject:set_local_pose(pose)
	local tr = SceneGraph.instance(self._sg, self._unit_id)
	if tr then SceneGraph.set_local_pose(self._sg, tr, pose) end
end

function SoundObject:on_selected(selected)
	self._selected = selected
	RenderWorld.selection(LevelEditor._rw, self._unit_id, selected);
end

function SoundObject:obb()
	local rw = LevelEditor._rw
	return RenderWorld.mesh_obb(rw, RenderWorld.mesh_instance(rw, self._unit_id))
end

function SoundObject:raycast(pos, dir)
	local rw = LevelEditor._rw
	local mesh = RenderWorld.mesh_instance(rw, self._unit_id)
	local tm, hext = RenderWorld.mesh_obb(rw, mesh)
	return RenderWorld.mesh_cast_ray(rw, mesh, pos, dir)
end

function SoundObject:draw()
	if self._selected then
		DebugLine.add_sphere(LevelEditor._lines
			, self:local_position()
			, self._range
			, Color4.yellow()
			)
	end
end

function SoundObject:set_range(range)
	self._range = range
end

function SoundObject:send()
	Device.console_send { type = "sound_spawned"
		, id = self._id
		, name = self:name()
		, position = self:local_position()
		, rotation = self:local_rotation()
		, scale = self:local_scale()
		, range = self._range
		, volume = self._volume
		, loop = self._loop
		}
end
