﻿-- chunkname: @scripts/utilities/luggable.lua

local MasterItems = require("scripts/backend/master_items")
local Pickups = require("scripts/settings/pickup/pickups")
local PlayerUnitVisualLoadout = require("scripts/extension_systems/visual_loadout/utilities/player_unit_visual_loadout")
local SLOT_LUGGABLE = "slot_luggable"
local Luggable = {}

Luggable.drop_luggable = function (t, unit, inventory_component, visual_loadout_extension, enable_physics)
	if not PlayerUnitVisualLoadout.slot_equipped(inventory_component, visual_loadout_extension, SLOT_LUGGABLE) then
		return
	end

	local unit_data_extension, existing_unit

	if enable_physics then
		unit_data_extension = ScriptUnit.extension(unit, "unit_data_system")

		local inventory_slot_component = unit_data_extension:read_component(SLOT_LUGGABLE)

		existing_unit = inventory_slot_component.existing_unit_3p
	end

	local wielded_slot = inventory_component.wielded_slot

	if wielded_slot == SLOT_LUGGABLE then
		local default_wielded_slot_name = Managers.state.game_mode:default_wielded_slot_name()

		PlayerUnitVisualLoadout.wield_slot(default_wielded_slot_name, unit, t)
	end

	PlayerUnitVisualLoadout.unequip_item_from_slot(unit, SLOT_LUGGABLE, t)

	if existing_unit and Managers.state.game_session:is_server() then
		local pickup_name = Unit.get_data(existing_unit, "pickup_type")
		local pickup_data = pickup_name and Pickups.by_name[pickup_name]

		if pickup_data and pickup_data.on_drop_func then
			pickup_data.on_drop_func(existing_unit, unit)
		end

		Managers.state.extension:system("pickup_system"):dropped(existing_unit)

		local first_person_component = unit_data_extension:read_component("first_person")
		local locomotion_component = unit_data_extension:read_component("locomotion")

		Luggable.enable_physics(first_person_component, locomotion_component, existing_unit)
	end
end

Luggable.enable_physics = function (first_person_component, locomotion_component, existing_unit)
	local look_position = first_person_component.position
	local look_rotation = first_person_component.rotation
	local look_direction = Quaternion.forward(look_rotation)
	local player_position = locomotion_component.position
	local position
	local projectile_locomotion_extension = ScriptUnit.has_extension(existing_unit, "locomotion_system")

	if projectile_locomotion_extension then
		local radius = projectile_locomotion_extension:radius()

		position = player_position + Vector3.up() * (radius * 1.1)
	else
		position = Vector3.lerp(player_position, look_position, 0.7)
	end

	local locomotion_extension = ScriptUnit.extension(existing_unit, "locomotion_system")
	local projectile_locomotion_template = locomotion_extension:locomotion_template()
	local throw_configuration = projectile_locomotion_template.trajectory_parameters.drop
	local inherit_owner_velocity_percentage = throw_configuration.inherit_owner_velocity_percentage
	local player_velocity = locomotion_component.velocity_current
	local player_velocity_contribution = player_velocity * inherit_owner_velocity_percentage
	local throw_speed = throw_configuration.speed
	local throw_velocity = throw_speed * look_direction
	local new_velocity = player_velocity_contribution + throw_velocity
	local angular_velocity = Vector3.zero()

	locomotion_extension:switch_to_engine_physics(position, look_rotation, new_velocity, angular_velocity)
end

Luggable.equip_to_player_unit = function (player_unit, luggable_unit, t)
	local locomotion_extension = ScriptUnit.extension(luggable_unit, "locomotion_system")
	local item_definitions = MasterItems.get_cached()
	local pickup_name = Unit.get_data(luggable_unit, "pickup_type")
	local pickup_data = Pickups.by_name[pickup_name]
	local inventory_item = item_definitions[pickup_data.inventory_item]

	if not inventory_item then
		Log.error("Luggable", "[equip_to_player_unit] missing item '%s'", pickup_data.inventory_item)

		return
	end

	locomotion_extension:switch_to_carried(player_unit)
	PlayerUnitVisualLoadout.equip_item_to_slot(player_unit, inventory_item, SLOT_LUGGABLE, luggable_unit, t)
	PlayerUnitVisualLoadout.wield_slot(SLOT_LUGGABLE, player_unit, t)
end

Luggable.link_to_player_unit = function (world, player_unit, luggable_unit, item)
	local attach_node = item.attach_node
	local breed_attach_node = item.breed_attach_node
	local unit_data_extension = ScriptUnit.extension(player_unit, "unit_data_system")
	local breed_name = unit_data_extension:breed_name()
	local attach_node_to_use = breed_attach_node[breed_name] or attach_node
	local node, map_nodes = Unit.node(player_unit, attach_node_to_use), false

	World.link_unit(world, luggable_unit, 1, player_unit, node, map_nodes)

	local visual_loadout_extension = ScriptUnit.extension(player_unit, "visual_loadout_system")

	visual_loadout_extension:force_update_item_visibility()
end

Luggable.unlink_from_player_unit = function (world, luggable_unit)
	local reset_scene_graph = false

	World.unlink_unit(world, luggable_unit, reset_scene_graph)
	Unit.set_unit_visibility(luggable_unit, true, true)
end

return Luggable
