local F={}function Selection.IsSelected(F)return Selection.ItemIndex[F]end function Selection.Add(w,v)local B=GetCore()local b={}for F,w in pairs(w)do if B.IsSelectable(w)and not Selection.ItemIndex[w]then table.insert(b,w)end end local x=Selection.Items for w,v in pairs(b)do Selection.ItemIndex[v]=true F[v]=v.AncestryChanged:connect(function(F,w)if w==nil then Selection.Remove({v})end end)end Selection.Items=Support.Keys(Selection.ItemIndex)if v and#b>0 then TrackSelectionChange(x)end CreateSelectionBoxes(b)Selection.ItemsAdded:fire(b)Selection.Changed:fire()end function Selection.Remove(w,v)local B={}for F,w in pairs(w)do if Selection.IsSelected(w)then table.insert(B,w)end end local b=Selection.Items for w,v in pairs(B)do Selection.ItemIndex[v]=nil F[v]:disconnect()F[v]=nil end RemoveSelectionBoxes(B)Selection.Items=Support.Keys(Selection.ItemIndex)if v and#B>0 then TrackSelectionChange(b)end Selection.ItemsRemoved:fire(B)Selection.Changed:fire()end function Selection.Clear(F)Selection.Remove(Selection.Items,F)Selection.Cleared:fire()end function Selection.Replace(F,w)local v=Selection.Items Selection.Clear(false)Selection.Add(F,false)if w then TrackSelectionChange(v)end end function Selection.SetFocus(F)if not Selection.IsSelected(F)and F~=nil then return end Selection.Focus=F Selection.FocusChanged:fire(F)end function FocusOnLastSelectedPart()if#Selection.Items==0 then Selection.SetFocus(nil)else Selection.SetFocus(Selection.Items[#Selection.Items])end end

local Listeners = {};

function Selection.IsSelected(Item)
	-- Returns whether `Item` is selected or not

	-- Check and return item presence in index
	return Selection.ItemIndex[Item];

end;

function Selection.Add(Items, RegisterHistory)
	-- Adds the given items to the selection

	-- Get core API
	local Core = GetCore();

	-- Go through and validate each given item
	local SelectableItems = {};
	for _, Item in pairs(Items) do

		-- Make sure each item is valid and not already selected
		if Core.IsSelectable(Item) and not Selection.ItemIndex[Item] then
			table.insert(SelectableItems, Item);
		end;

	end;

	local OldSelection = Selection.Items;

	-- Go through the valid new selection items
	for _, Item in pairs(SelectableItems) do

		-- Add each valid item to the selection
		Selection.ItemIndex[Item] = true;

		-- Deselect items that are destroyed
		Listeners[Item] = Item.AncestryChanged:connect(function (Object, Parent)
			if Parent == nil then
				Selection.Remove({ Item });
			end;
		end);

	end;

	-- Update selected item list
	Selection.Items = Support.Keys(Selection.ItemIndex);

	-- Create a history record for this selection change, if requested
	if RegisterHistory and #SelectableItems > 0 then
		TrackSelectionChange(OldSelection);
	end;

	-- Create selection boxes for the selection
	CreateSelectionBoxes(SelectableItems);

	-- Fire relevant events
	Selection.ItemsAdded:fire(SelectableItems);
	Selection.Changed:fire();

end;

function Selection.Remove(Items, RegisterHistory)
	-- Removes the given items from the selection

	-- Go through and validate each given item
	local DeselectableItems = {};
	for _, Item in pairs(Items) do

		-- Make sure each item is actually selected
		if Selection.IsSelected(Item) then
			table.insert(DeselectableItems, Item);
		end;

	end;

	local OldSelection = Selection.Items;

	-- Go through the valid deselectable items
	for _, Item in pairs(DeselectableItems) do

		-- Remove item from selection
		Selection.ItemIndex[Item] = nil;

		-- Stop tracking item's parent
		Listeners[Item]:disconnect();
		Listeners[Item] = nil;

	end;

	-- Remove selection boxes from deselected items
	RemoveSelectionBoxes(DeselectableItems);

	-- Update selected item list
	Selection.Items = Support.Keys(Selection.ItemIndex);

	-- Create a history record for this selection change, if requested
	if RegisterHistory and #DeselectableItems > 0 then
		TrackSelectionChange(OldSelection);
	end;

	-- Fire relevant events
	Selection.ItemsRemoved:fire(DeselectableItems);
	Selection.Changed:fire();

end;

function Selection.Clear(RegisterHistory)
	-- Clears all items from selection

	-- Remove all selected items
	Selection.Remove(Selection.Items, RegisterHistory);

	-- Fire relevant events
	Selection.Cleared:fire();

end;

function Selection.Replace(Items, RegisterHistory)
	-- Replaces the current selection with the given new items

	-- Save old selection reference for history
	local OldSelection = Selection.Items;

	-- Clear current selection and select new items
	Selection.Clear(false);
	Selection.Add(Items, false);

	-- Create a history record for this selection change, if requested
	if RegisterHistory then
		TrackSelectionChange(OldSelection);
	end;

end;

function Selection.SetFocus(Item)
	-- Selects `Item` as the focused selection item

	-- Make sure the item is selected or is `nil`
	if not Selection.IsSelected(Item) and Item ~= nil then
		return;
	end;

	-- Set the item as the focus
	Selection.Focus = Item;

	-- Fire relevant events
	Selection.FocusChanged:fire(Item);

end;

function FocusOnLastSelectedPart()
	-- Sets the last part of the selection as the focus

	-- If selection is empty, clear the focus
	if #Selection.Items == 0 then
		Selection.SetFocus(nil);

	-- Otherwise, focus on the last part in the selection
	else
		Selection.SetFocus(Selection.Items[#Selection.Items]);
	end;

end;
