--===========================================================================================================================>
--!optimize 2
--!native
--!strict
--===========================================================================================================================>

-- Set Memory Category:
debug.setmemorycategory("[Zoner]: Detection")

--===========================================================================================================================>
--[ DEPENDENCIES: ]

-- [ Global Requires ]

local WorldModel = require(`../WorldModel`)
local Groups     = require(`../../Groups`)

-- [ Internals ]
local Enums = require(script:FindFirstAncestor('Internal').Data.Enums.All);

-- [ Sub Requires ]

local Bounds    = require(`@self/Bounds`)
local Targets   = require(`@self/Targets`)
local Tracker   = require(`@self/Tracker`)
local Coverages = require(`@self/Coverages`)

-- Define Module table
-- Key tables by Enums:
local DetectionHandlers = {
	[Enums.DetectionMethod.ENUMS.Complex]   = {},
	[Enums.DetectionMethod.ENUMS.Simple]    = {},
	[Enums.DetectionMethod.ENUMS.Efficient] = {}
}

--===========================================================================================================================>
--[ CONSTANTS: ]

-- Constant Enum Variables:
local ENTERED: number, EXITED: number, IN: number, OUT: number = 1, 2, 3, 4

-- Function to use on Evaluate:
local DO_NOTHING = function() end

--===========================================================================================================================>
--[ TYPES: ]

-- [ Require Types ]

-- This will inject all types into this context.
local ZonePrimitives = require('../../../Types/ZonePrimitives')
local ZoneInstances  = require('../../../Types/ZoneInstances')
local ZoneTargets    = require('../../../Types/ZoneTargets')
local ZoneConfig     = require('../../../Types/ZoneConfig')
local ZoneState      = require('../../../Types/ZoneState')

-- [ Define Types ]

-- Define the Tracker Status function used to Get the Specific Status based on bounds:
type TrackerStatusFunction = (
	ZoneId: string,
	Tracker: Tracker.Tracker<Tracker.Trackables>,
	HitTargetParts: { BasePart }?
) -> number

-- Define ZoneEngine Data/Profile sent from ZoneEngine:
type ZoneEngineData = {
	ZoneContainer:     ZonePrimitives.ZoneContainer,
	ZoneContainerType: ZonePrimitives.ZoneContainerType,
	ZoneConfig:        ZoneConfig.ZoneConfigTable,
	ZoneStates:        ZoneState.ZoneStatesTable,
	ZoneFolder:        ZoneInstances.ZoneFolder,
	ZonePieces:        ZonePrimitives.ZonePieces,
	ZoneId:            string,

	ZoneSignalEvent: BindableEvent?,
	ZoneSignalFunction: ((Purpose: string, ...any) -> ())?,
}

-- Export the Object:
export type DetectionHandler = {
	--====================================================>
	Destroying: boolean,
	Detecting: boolean,
	--====================================================>
	_BoundsHandler: Bounds.BoundsHandler,

	_TargetHandlers: { [string]: Targets.TargetHandler },

	--====================================================>
	_CurrentParts: { [BasePart]: boolean },

	_OverlapParamaters: {
		PartsExcludeList: OverlapParams,
	}?,

	AddBoundsEvaluateFunction: (self: DetectionHandler, Target: Targets.TargetTypes) -> (),
	AddTargetHandler: (self: DetectionHandler, Target: Targets.TargetTypes) -> (),
	RemoveBoundsEvaluateFunction: (self: DetectionHandler, Target: Targets.TargetTypes) -> (),
	RemoveTargetHandler: (self: DetectionHandler, Target: Targets.TargetTypes) -> (),

	AddToCurrentParts: (self: DetectionHandler, Parts: { BasePart }) -> (),
	AddOverlapParamaters: (self: DetectionHandler) -> (),
	RemoveOverlapParamaters: (self: DetectionHandler) -> (),
	RemoveCurrentParts: (self: DetectionHandler) -> (),

	UpdateDetectionCoverage: (self: DetectionHandler) -> (),

	GetBoundsHandler: (self: DetectionHandler) -> Bounds.BoundsHandler,
	GetDetectionStatus: (self: DetectionHandler) -> boolean,

	-- Function that will run the location checking code for the passed in Tracker and set its location status as well as add it to the
	-- Entrance or Exit table on the TargetHandler depending on its location status:
	ComputeTrackerLocation: (
		self: DetectionHandler,
		Key: string,
		TargetHandler: Targets.TargetHandler,
		Tracker: Tracker.Tracker<Tracker.Trackables>,
		TrackerHitParts: { BasePart }?
	) -> (),

	ComputePartLocations: (self: DetectionHandler, TargetHandler: Targets.TargetHandler) -> (),

	-- We send Active Signals table from the Engine instead of storing it as a reference here:
	FireSignals: (self: DetectionHandler, ActiveSignals: ZoneTargets.ZoneActiveSignalsTable) -> (),

	Evaluate: (self: DetectionHandler) -> (),

	--====================================================>
	Destroy: (self: DetectionHandler) -> (),
	--====================================================>
}

--===========================================================================================================================>

-- Function to Fire Signals in Parallel:
local function FireSignals_Parallel(
	TargetHandlers: { [string]: Targets.TargetHandler },
	ZoneId: string,
	ZoneSignal: BindableEvent,
	ActiveSignals: ZoneTargets.ZoneActiveSignalsTable
)
	--=======================================================================================================>
	-- Loop through all the target handlers to run each of their signals:
	for Target, TargetHandler: Targets.TargetHandler in TargetHandlers do
		--========================================================================================>
		-- Get a Boolean on Whether Entered is Empty
		local EnteredIsEmpty, ExitedIsEmpty =
			(TargetHandler:GetEntered()[1] == nil), (TargetHandler:GetExited()[1] == nil)

		-- If Both Entered and Exited Arrays are empty than continue loop:
		if EnteredIsEmpty and ExitedIsEmpty then
			continue
		end

		--========================================================================================>
		-- We will dynamically index the Active Signal boolean via the Target Name (Part, Item, Player, LocalPlayer)
		-- and then we will concat the type of signal we are checking (Entered or Exited) and check whether its currently activew
		-- before we go ahead with firing its event:

		-- If the Entered Array is not Empty, loop through it and then Clear its Array:
		if EnteredIsEmpty == false then
			-- If the Signal indexed is Active (has connections)
			if ActiveSignals[`{Target}Entered`] == true then
				-- Loop through the Entered Values:
				for Index: number, Value: any in ipairs(TargetHandler:GetEntered()) do
					ZoneSignal:Fire(ZoneId, TargetHandler.EnteredHash, Value)
				end
			end
			-- Clear Array:
			TargetHandler:ClearEntered()
		end

		-- If the Exited Array is not Empty, loop through it and then Clear its Array:
		if ExitedIsEmpty == false then
			-- If the Signal indexed is Active (has connections)
			if ActiveSignals[`{Target}Exited`] == true then
				-- Loop through the Exited Values:
				for Index: number, Value: any in ipairs(TargetHandler:GetExited()) do
					ZoneSignal:Fire(ZoneId, TargetHandler.ExitedHash, Value)
				end
			end
			-- Clear Array:
			TargetHandler:ClearExited()
		end

		--========================================================================================>
	end
	--=======================================================================================================>
end

-- Function to Fire Signals in Serial:
local function FireSignals_Serial(
	TargetHandlers: { [string]: Targets.TargetHandler },
	ZoneId: string,
	ZoneSignalFunction: (Purpose: string, ...any) -> (),
	ActiveSignals: ZoneTargets.ZoneActiveSignalsTable
)
	--=======================================================================================================>
	-- Loop through all the target handlers to run each of their signals:
	for Target, TargetHandler: Targets.TargetHandler in TargetHandlers do
		--========================================================================================>

		-- Get a Boolean on Whether Entered is Empty
		local EnteredIsEmpty, ExitedIsEmpty =
			(TargetHandler:GetEntered()[1] == nil), (TargetHandler:GetExited()[1] == nil)

		-- If Both Entered and Exited Arrays are empty than continue loop:
		if EnteredIsEmpty and ExitedIsEmpty then
			continue
		end

		--========================================================================================>
		-- We will dynamically index the Active Signal boolean via the Target Name (Part, Item, Player, LocalPlayer)
		-- and then we will concat the type of signal we are checking (Entered or Exited) and check whether its currently activew
		-- before we go ahead with firing its event:

		-- If the Entered Array is not Empty, loop through it and then Clear its Array:
		if EnteredIsEmpty == false then
			-- If the Signal indexed is Active (has connections)
			if ActiveSignals[`{Target}Entered`] == true then
				-- Loop through the Entered Values:
				for Index: number, Value: any in ipairs(TargetHandler:GetEntered()) do
					ZoneSignalFunction(TargetHandler.EnteredHash, Value)
				end
			end
			-- Clear Array:
			TargetHandler:ClearEntered()
		end

		-- If the Exited Array is not Empty, loop through it and then Clear its Array:
		if ExitedIsEmpty == false then
			-- If the Signal indexed is Active (has connections)
			if ActiveSignals[`{Target}Exited`] == true then
				-- Loop through the Exited Values:
				for Index: number, Value: any in ipairs(TargetHandler:GetExited()) do
					ZoneSignalFunction(TargetHandler.ExitedHash, Value)
				end
			end
			-- Clear Array:
			TargetHandler:ClearExited()
		end

		--========================================================================================>
	end
	--=======================================================================================================>
end

--===========================================================================================================================>

-- Constructor function which is used by every DetectionHandler type in order to inherit core functions and values shared by all types:
local function DetectionHandler(EngineData: ZoneEngineData): DetectionHandler
	--=======================================================================================================>

	-- Locally define Function references:
	local GetTrackerStatus: TrackerStatusFunction

	-- Define the TargetData and Inherit from the Base Class:
	local DetectionData: DetectionHandler = {
		--====================================================>
		Detecting = false,
		Destroying = false,
		--====================================================>
		_TargetHandlers = {},
		--====================================================>
		_CurrentParts = {},
		--====================================================>
		-- Construct a new Handler Object with the Trove and Set it in the Table:
		-- Index the Target Specific Table with the Target Name to gets its New Method:
		_BoundsHandler = Bounds[EngineData.ZoneConfig.Bounds].New(EngineData),
		--====================================================>
	} :: DetectionHandler

	--=======================================================================================================>

	-- Set the Evaluate Function to 'DO_NOTHING':
	DetectionData._BoundsHandler.Evaluate = DO_NOTHING

	-- If the Zone Engine is in Serial, and a ZoneSignal Function is passed, Construct a FireSignals function that is meant
	-- for using the ZoneSignal Callback function:
	-- else use the BindableEvent version. Construct an empty function if nothing is present as a saftey percaution:
	if EngineData.ZoneSignalFunction then
		function DetectionData.FireSignals(self: DetectionHandler, ActiveSignals: ZoneTargets.ZoneActiveSignalsTable)
			FireSignals_Serial(
				DetectionData._TargetHandlers,
				EngineData.ZoneId,
				EngineData.ZoneSignalFunction,
				ActiveSignals
			)
		end
	elseif EngineData.ZoneSignalEvent then
		function DetectionData.FireSignals(self: DetectionHandler, ActiveSignals: ZoneTargets.ZoneActiveSignalsTable)
			FireSignals_Parallel(
				DetectionData._TargetHandlers,
				EngineData.ZoneId,
				EngineData.ZoneSignalEvent,
				ActiveSignals
			)
		end
	else
		function DetectionData.FireSignals(self: DetectionHandler, ActiveSignals: ZoneTargets.ZoneActiveSignalsTable)
			warn("Empty FireSignals Function, something seriously wrong")
		end
	end

	--=======================================================================================================>

	-- Function that return the BoundsHandler Object:
	function DetectionData.UpdateDetectionCoverage(self: DetectionHandler)
		--============================================================================================>
		if
			EngineData.ZoneConfig.DetectionMethod == Enums.DetectionMethod.ENUMS.Complex
			or DetectionData._BoundsHandler:GetBoundType() == "PerPart"
		then
			--=================================================================================>
			-- Cache the Coverage Function:
			local InZoneCoverage = Coverages.InZoneParts[EngineData.ZoneConfig.DetectionCoverage]
			-- Cache the BoundsHandler:
			local BoundsHandler = DetectionData._BoundsHandler
			--=================================================================================>

			-- If Enter and Exit Detection Coverage's are set:
			if EngineData.ZoneConfig.EnterDetectionCoverage or EngineData.ZoneConfig.ExitDetectionCoverage then
				-- Local ExitDetection Coverage var
				local Exit_DetectionCoverage

				-- This will auto swap AllParts and AnyPart detection coverage functionality, because on exit, its the opposite
				-- logic that we want:
				if EngineData.ZoneConfig.ExitDetectionCoverage then
					if EngineData.ZoneConfig.ExitDetectionCoverage == Enums.DetectionCoverage.ENUMS.AllParts then
						Exit_DetectionCoverage = Enums.DetectionCoverage.ENUMS.AnyPart
					elseif
						EngineData.ZoneConfig.ExitDetectionCoverage == Enums.DetectionCoverage.ENUMS.AnyPart
					then
						Exit_DetectionCoverage = Enums.DetectionCoverage.ENUMS.AllParts
					else
						Exit_DetectionCoverage = EngineData.ZoneConfig.ExitDetectionCoverage
					end
				end

				-- Cache the Coverage Function:
				local InZoneCoverage_Enter = if EngineData.ZoneConfig.EnterDetectionCoverage
					then Coverages.InZoneParts[EngineData.ZoneConfig.EnterDetectionCoverage]
					else InZoneCoverage
				-- Cache the Coverage Function:
				local InZoneCoverage_Exit = if Exit_DetectionCoverage
					then Coverages.InZoneParts[Exit_DetectionCoverage]
					else InZoneCoverage

				local DetectionMode_Enter = EngineData.ZoneConfig.EnterDetectionMode
					or EngineData.ZoneConfig.DetectionMode
				local DetectionMode_Exit = EngineData.ZoneConfig.ExitDetectionMode
					or EngineData.ZoneConfig.DetectionMode

				-- Create the function for Boxes:
				GetTrackerStatus = function(
					ZoneId: string,
					Tracker: Tracker.Tracker<Tracker.Trackables>,
					HitTargetParts: { BasePart }?
				): number
					--=======================================================================================================>
					-- If the Tracker is NOT currently in the Zone, check its entrance:
					if Tracker:InZone(ZoneId) ~= true then
						-- If the Player is now in the zone, add it to the entered table, else, exited, else do nothing:
						if
							InZoneCoverage_Enter(
								Tracker:GetPartsList(),
								DetectionMode_Enter,
								BoundsHandler:GetZonePartDetailsMap(),
								HitTargetParts
							)
						then
							return ENTERED
						else
							return OUT
						end
					else
						-- If the Player is now in the zone, add it to the entered table, else, exited, else do nothing:
						if
							InZoneCoverage_Exit(
								Tracker:GetPartsList(),
								DetectionMode_Exit,
								BoundsHandler:GetZonePartDetailsMap(),
								HitTargetParts
							)
						then
							return IN
						else
							return EXITED
						end
					end
					--=======================================================================================================>
				end
			else
				-- Create the function for Boxes:
				GetTrackerStatus = function(
					ZoneId: string,
					Tracker: Tracker.Tracker<Tracker.Trackables>,
					HitTargetParts: { BasePart }?
				): number
					--=======================================================================================================>
					-- If the Player is now in the zone, add it to the entered table, else, exited, else do nothing:
					if
						InZoneCoverage(
							Tracker:GetPartsList(),
							EngineData.ZoneConfig.DetectionMode,
							BoundsHandler:GetZonePartDetailsMap(),
							HitTargetParts
						)
					then
						-- If the PlayerInZone State Previously was False as in not in the Zone, then Player is Entering:
						return if Tracker:InZone(ZoneId) ~= true then ENTERED else IN
					else
						-- If the PlayerInZone State Previously was True as in was in the Zone, then Player is Exiting:
						return if Tracker:InZone(ZoneId) == true then EXITED else OUT
					end
					--=======================================================================================================>
				end
			end
			--=================================================================================>
		else
			--=================================================================================>
			-- Cache the Coverage Function:
			local InZoneCoverage = Coverages.InBox[EngineData.ZoneConfig.DetectionCoverage]

			-- Cache the ZoneBoxData:
			local ZoneBoxData = DetectionData._BoundsHandler.ZoneBoxData

			-- If Enter and Exit Detection Coverage's are set:
			if EngineData.ZoneConfig.EnterDetectionCoverage or EngineData.ZoneConfig.ExitDetectionCoverage then
				-- Local ExitDetection Coverage var
				local Exit_DetectionCoverage

				-- This will auto swap AllParts and AnyPart detection coverage functionality, because on exit, its the opposite
				-- logic that we want:
				if EngineData.ZoneConfig.ExitDetectionCoverage then
					if EngineData.ZoneConfig.ExitDetectionCoverage == Enums.DetectionCoverage.ENUMS.AllParts then
						Exit_DetectionCoverage = Enums.DetectionCoverage.ENUMS.AnyPart
					elseif
						EngineData.ZoneConfig.ExitDetectionCoverage == Enums.DetectionCoverage.ENUMS.AnyPart
					then
						Exit_DetectionCoverage = Enums.DetectionCoverage.ENUMS.AllParts
					else
						Exit_DetectionCoverage = EngineData.ZoneConfig.ExitDetectionCoverage
					end
				end

				-- Cache the Coverage Function:
				local InZoneCoverage_Enter = if EngineData.ZoneConfig.EnterDetectionCoverage
					then Coverages.InBox[EngineData.ZoneConfig.EnterDetectionCoverage]
					else InZoneCoverage

				-- Cache the Coverage Function:
				local InZoneCoverage_Exit = if Exit_DetectionCoverage
					then Coverages.InBox[Exit_DetectionCoverage]
					else InZoneCoverage

				local DetectionMode_Enter = EngineData.ZoneConfig.EnterDetectionMode
					or EngineData.ZoneConfig.DetectionMode
				local DetectionMode_Exit = EngineData.ZoneConfig.ExitDetectionMode
					or EngineData.ZoneConfig.DetectionMode

				-- Create the function for Boxes:
				GetTrackerStatus = function(
					ZoneId: string,
					Tracker: Tracker.Tracker<Tracker.Trackables>,
					HitTargetParts: { BasePart }?
				): number
					--=======================================================================================================>
					-- If the Tracker is NOT currently in the Zone, check its entrance:
					if Tracker:InZone(ZoneId) ~= true then
						-- If the Player is now in the zone, add it to the entered table, else, exited, else do nothing:
						if
							InZoneCoverage_Enter(
								Tracker:GetPartsList(),
								DetectionMode_Enter,
								ZoneBoxData.CFrame,
								ZoneBoxData.HalfSize,
								HitTargetParts
							)
						then
							return ENTERED
						else
							return OUT
						end
					else
						-- If the Player is now in the zone, add it to the entered table, else, exited, else do nothing:
						if
							InZoneCoverage_Exit(
								Tracker:GetPartsList(),
								DetectionMode_Exit,
								ZoneBoxData.CFrame,
								ZoneBoxData.HalfSize,
								HitTargetParts
							)
						then
							return IN
						else
							return EXITED
						end
					end
					--=======================================================================================================>
				end
			else
				-- Create the function for Boxes:
				GetTrackerStatus = function(
					ZoneId: string,
					Tracker: Tracker.Tracker<Tracker.Trackables>,
					HitTargetParts: { BasePart }?
				): number
					--=======================================================================================================>
					-- If the Player is now in the zone, add it to the entered table, else, exited, else do nothing:
					if
						InZoneCoverage(
							Tracker:GetPartsList(),
							EngineData.ZoneConfig.DetectionMode,
							ZoneBoxData.CFrame,
							ZoneBoxData.HalfSize,
							HitTargetParts
						)
					then
						-- If the PlayerInZone State Previously was False as in not in the Zone, then Player is Entering:
						return if Tracker:InZone(ZoneId) ~= true then ENTERED else IN
					else
						-- If the PlayerInZone State Previously was True as in was in the Zone, then Player is Exiting:
						return if Tracker:InZone(ZoneId) == true then EXITED else OUT
					end
					--=======================================================================================================>
				end
			end

			--=================================================================================>
		end
		--============================================================================================>
	end

	--=======================================================================================================>
	--[ ADDER/REMOVER METHODS: ]

	-- Adds a new TargetHandler Object on this DetectionHandler Object:
	function DetectionData.AddTargetHandler(self: DetectionHandler, Target: Targets.TargetTypes)
		--============================================================================================>
		-- If a TargetHandler Object for this Target exists already, Call the same Function but with State as False to Destroy it,
		-- Then continue to make a new Object:
		if self._TargetHandlers[Target] then
			self:RemoveTargetHandler(Target)
		end
		-- Construct a new Handler Object with the Trove and Set it in the Table:
		-- Index the Target Specific Table with the Target Name to gets its New Method:
		self._TargetHandlers[Target] = Targets[Target].New(
			-- Pass in a Boolean on whether the Execution is Serial or not:
			EngineData.ZoneConfig.Execution == Enums.Execution.ENUMS.Serial
		)
		--============================================================================================>
		-- Set the Detection Status based on the Targets:
		self.Detecting = self:GetDetectionStatus()
		--============================================================================================>
		-- When a TargetHandler is added create the Overlap Paramaters if needed:
		if Target == "Part" or EngineData.ZoneConfig.DetectionMethod ~= Enums.DetectionMethod.ENUMS.Efficient then
			self:AddOverlapParamaters()
			self:AddBoundsEvaluateFunction(Target)
		end
		--============================================================================================>
	end

	-- Function which Adds an Array of Parts to the CurrentParts Dictionary without adding duplicates:
	function DetectionData.AddToCurrentParts(self: DetectionHandler, Parts: { BasePart })
		--===============================================================================>
		-- Loop through the Results from the Single Part of the Zone, and Check to make sure each Part is not already in the
		-- Global Zone Results Table, if its not already added to the Results Array, Insert it to combine the zone parts:
		for Index: number, Result: BasePart in ipairs(Parts) do
			-- Check to see if the Result is already added, continue if so:
			if self._CurrentParts[Result] then
				continue
			end
			-- Insert Result to Results Table:
			self._CurrentParts[Result] = true
		end
		--===============================================================================>
	end

	-- Function which will Add OverlapParamater Instances to the Object:
	function DetectionData.AddOverlapParamaters(self: DetectionHandler)
		--===============================================================================>
		-- If they are already created then return:
		if self._OverlapParamaters then
			return
		end

		-- Define the OverlapParams Table:
		self._OverlapParamaters = {
			PartsExcludeList = OverlapParams.new(),
		}

		-- For Type Checking reasons, make sure its not nil:
		if not self._OverlapParamaters then
			return
		end

		self._OverlapParamaters.PartsExcludeList.FilterType = Enum.RaycastFilterType.Exclude
		self._OverlapParamaters.PartsExcludeList.FilterDescendantsInstances = {}
		self._OverlapParamaters.PartsExcludeList.CollisionGroup = "Zoner:ZonePart"

		--===============================================================================>
	end

	--=======================================================================================================>

	-- Function which will Remove OverlapParamater Instances from the Object:
	function DetectionData.RemoveOverlapParamaters(self: DetectionHandler)
		if self._OverlapParamaters == nil then
			return
		end
		self._OverlapParamaters = nil :: any
	end

	-- Removes an Existing TargetHandler Object from exisistance on this DetectionHandler Object:
	function DetectionData.RemoveTargetHandler(self: DetectionHandler, Target: Targets.TargetTypes)
		--===============================================================================>
		-- If a TargetHandler Object exists, then Remove/Destroy it in the Trove and Set its Table value to nil:
		if self._TargetHandlers[Target] then
			-- Loop through all the still existing Trackers in the Target Handler, and Make each Exit the current Zone:
			for Key, Tracker in self._TargetHandlers[Target]:GetTrackers() do
				if Tracker:InZone(EngineData.ZoneId) then
					Tracker:ExitZone(EngineData.ZoneId)
				end
			end

			self._TargetHandlers[Target]:Destroy()
			self._TargetHandlers[Target] = nil
		end
		--===============================================================================>
		-- Set the Detection Status based on the Targets:
		self.Detecting = self:GetDetectionStatus()
		--===============================================================================>
		-- If the DetectionType is not 'Efficient', then we need to check if any other Targets are Active.
		-- If any other target is active, then dont remove the overlap, if they're none, then remove overlap:
		if Target == "Part" then
			if EngineData.ZoneConfig.DetectionMethod ~= Enums.DetectionMethod.ENUMS.Efficient then
				-- If none are active, then remove overlap paramaters, and remove the evaluatefunction:
				self:RemoveOverlapParamaters()
				self:RemoveBoundsEvaluateFunction(Target)
				-- If we are still Detecting, as in theres other TargetHandlers other than Part active, loop
				-- through them and Add back the OverlapParams and EvaluateFunction that was removed, and break once
				-- it does it once:
				if self.Detecting == true then
					for Key, Handler in self._TargetHandlers do
						self:AddOverlapParamaters()
						self:AddBoundsEvaluateFunction(Target)
						break
					end
				end
			else
				self:RemoveOverlapParamaters()
				self:RemoveBoundsEvaluateFunction(Target)
			end
		else
			if EngineData.ZoneConfig.DetectionMethod ~= Enums.DetectionMethod.ENUMS.Efficient then
				-- If none are active, then remove overlap paramaters:
				if self.Detecting == false then
					self:RemoveOverlapParamaters()
					self:RemoveBoundsEvaluateFunction(Target)
				end
			end
		end
		--===============================================================================>
	end

	-- Function which clears the current parts table:
	function DetectionData.RemoveCurrentParts(self: DetectionHandler)
		table.clear(self._CurrentParts)
	end

	--=======================================================================================================>
	--[ GETTER METHODS: ]

	-- Function that return the BoundsHandler Object:
	function DetectionData.GetDetectionStatus(self: DetectionHandler): boolean
		--==============================================================================================>
		-- Boolean to store whether a Target Exists:
		local TargetExists = false
		-- Loop through the Targets, break at the first one in the dictionary if populated:
		for Key, Target in self._TargetHandlers do
			TargetExists = true
			break
		end
		-- If none are active and existing, then detection status is false, else detection status is true:
		if TargetExists == false then
			return false
		else
			return true
		end
		--==============================================================================================>
	end

	-- Function that return the BoundsHandler Object:
	function DetectionData.GetBoundsHandler(self: DetectionHandler): Bounds.BoundsHandler
		return self._BoundsHandler
	end

	--=======================================================================================================>
	--[ CORE METHODS: ]

	-- Function that will run the location checking code for the passed in Tracker and set its location status as well as add it to the
	-- Entrance or Exit table on the TargetHandler depending on its location status:
	function DetectionData.ComputeTrackerLocation(
		self: DetectionHandler,
		Key: string,
		TargetHandler: Targets.TargetHandler,
		Tracker: Tracker.Tracker<Tracker.Trackables>,
		TrackerHitParts: { BasePart }?
	)
		--==============================================================================================>

		-- 9/13/2025:  Began Exclusive Group Implementation:
		-- 10/10/2025: Finished Exclusive Group Implementation:

		-- Boolean as to whether the TrackerStatus detection code will run:
		-- This is used to skip detection for this Zone if it currently is unable to detect due
		-- to a group exclusivity restriction:
		local CAN_RUN_TRACKER_DETECTION: boolean = true

		-- Loop through all the existing Zone Groups to find which Groups the current Detecting Zone is in:
		-- Since we do not keep a dictionary of Groups the Zone is in on the Engine Object:
		for GroupKey: string, GroupData in Groups.ZoneGroups do
			-- If the TrackerStatus is no longer 'ENTERED' then we Break the Loop to stop schecking for an Out:
			if CAN_RUN_TRACKER_DETECTION == false then break end
			-- If the Current Detector's Parent Zone is not in the iterated group, continue:
			if not (GroupData.Zones[EngineData.ZoneId]) then continue end
			-- Tracker:GetZoneIdMap() -> Get's a Dictionary of all the Zone's this TrackedItem is currently in:
			-- Check if Tracker is in any other Zones that also share the same group, to then check mutal properties of the group:
			for ZoneId: string, Status: boolean in Tracker:GetZoneIDMap() do
				-- If the ZoneId is the same as the current checking Zone, continue:
				if ZoneId == EngineData.ZoneId then continue end
				-- If the Existing Zone the TrackedItem is currently in matches the Group the Detecting Zone is currently in...
				-- continue on in the scope to check shared properties of the group
				if not (GroupData.Zones[ZoneId]) then continue end
				-- If the Shared Group's Properties have 'Exclusive' as true, then do not allow the detecting Zone to be entered
				-- Since with the 'Exclusive' Property, only one Zone of the Group can be entered at the same time:
				if GroupData.Properties.Exclusive == true then
					-- Set the TrackerStatus to OUT and Break the Loop:
					CAN_RUN_TRACKER_DETECTION = false; break
				end
			end
		end

		-- If the Boolean is false, cancel early and dont do Zone Detection checks:
		if CAN_RUN_TRACKER_DETECTION == false then return end

		-- Get the Status of the Tracked Item relative to this Zone:
		-- Just realized, this is actually quite performant ngl.
		local TrackerStatus: number = GetTrackerStatus(EngineData.ZoneId, Tracker, TrackerHitParts)

		-- Run Entrance and Exit Logic based on Enum:
		if TrackerStatus == ENTERED then
			-- Add the Tracker to the Entered Array:
			TargetHandler:AddToEntered(TargetHandler:GetTargetItem(Key, Tracker))
			-- Add ZoneId to the map:
			Tracker:EnterZone(EngineData.ZoneId)
		elseif TrackerStatus == EXITED then
			-- Add the Tracker to the Exited Array:
			TargetHandler:AddToExited(TargetHandler:GetTargetItem(Key, Tracker))
			-- Remove ZoneId from the map:
			Tracker:ExitZone(EngineData.ZoneId)
		end
		--==============================================================================================>
	end

	-- Function that will run the location checking code for the passed in Par TargetHandler
	-- and set its location status as well as add it to the
	-- Entrance or Exit table on the TargetHandler depending on its location status:
	function DetectionData.ComputePartLocations(self: DetectionHandler, TargetHandler: Targets.TargetHandler)
		--==============================================================================================>

		-- Cache for quick access
		local CurrentParts: { [BasePart]: boolean } = self._CurrentParts
		local TargetCurrent: { [BasePart]: boolean } = TargetHandler.Current :: any

		-- Exit check — items that were tracked but are no longer present
		for Part: BasePart, _ in TargetCurrent do
			if not CurrentParts[Part] then
				-- Clear the Part from the Current Parts Dictionary
				TargetCurrent[Part] = nil -- Remove from current
				TargetHandler:AddToExited(Part) -- Mark as exited
			end
		end

		-- Entry check — new parts that weren't tracked before
		for Part: BasePart, _ in CurrentParts do
			if not TargetCurrent[Part] then
				-- Add the Part to the Current Parts Dictionary
				TargetCurrent[Part] = true -- Add to current
				TargetHandler:AddToEntered(Part) -- Mark as entered
			end
		end

		-- Clear variables:
		CurrentParts, TargetCurrent = nil :: any, nil :: any

		--==============================================================================================>
	end

	-- Method that will destroy the object and clean up all interior data:
	function DetectionData.Destroy(self: DetectionHandler)
		--==============================================================================================>

		-- If Destroying is already true then return:
		if self.Destroying == true then
			return
		else
			self.Destroying = true
		end

		--==============================================================================================>

		-- Remove all Target Handlers:
		for Key, Target in self._TargetHandlers do
			-- Remove the Target Handler:
			self:RemoveTargetHandler(Key :: any)
		end

		-- Clear Table:
		self:RemoveCurrentParts()
		-- Remove Table:
		self:RemoveOverlapParamaters()

		-- Destroy the BoundsHandler:
		self._BoundsHandler:Destroy()

		-- Clear all self data:
		for Index, Data in pairs(self) do
			self[Index] = nil
		end

		--==============================================================================================>
	end

	--=======================================================================================================>

	-- Update internal Detection Coverage:
	DetectionData:UpdateDetectionCoverage()

	--=======================================================================================================>

	-- Return the DetectionHandler Object:
	return DetectionData :: DetectionHandler

	--=======================================================================================================>
end

--===========================================================================================================================>

-- Constructor function that will create a "Complex" DetectionHandler and return the Object after inheriting from "Default":
DetectionHandlers[Enums.DetectionMethod.ENUMS.Complex].New = function(EngineData: ZoneEngineData): DetectionHandler
	--=======================================================================================================>

	-- Set Memory Category:
	debug.setmemorycategory("[Zoner]: Detection")

	-- Define the TargetData and Inherit from the Base Class:
	local DetectionData: DetectionHandler = DetectionHandler(EngineData) :: DetectionHandler

	--=======================================================================================================>

	-- Function which will Add the BoundsHandler's Evaluate function:
	function DetectionData.AddBoundsEvaluateFunction(self: DetectionHandler, TargetTypes: Targets.TargetTypes)
		--==============================================================================================>
		-- If no OverlapParams, return:
		if not self._OverlapParamaters then
			return
		end

		-- if the BoundsHandler Evaluate function is already set, and the TargetTypes is not Part, return:
		if self._BoundsHandler.Evaluate ~= DO_NOTHING and TargetTypes ~= "Part" then
			return
		end

		-- Local reference for less indexing:
		-- If Part is the target type, we will make the Params GRAB everything, vs Player Include list:
		local OverlapParamaters: OverlapParams = if TargetTypes == "Part"
			then self._OverlapParamaters.PartsExcludeList
			else self._OverlapParamaters.PartsExcludeList

		-- Bind Bound Type Specific EvaluateCallbacks for easy runtime function calls:
		self._BoundsHandler.Evaluate = function(BoundsHandler: Bounds.BoundsHandler)
			--=======================================================================================>
			-- Loop through the ZoneParts that make up the Zone:
			for ZonePart, Details in BoundsHandler:GetZonePartDetailsMap() do
				--===============================================================================>
				-- Get the Results of the Inidividual Part of the Zone:
				-- Loop through the Results from the Single Part of the Zone, and Check to make sure each Part is not already in the
				-- Global Zone Results Table, if its not already added to the Results Array, Insert it to combine the zone parts:
				self:AddToCurrentParts(
					WorldModel:GetPartsInPart(
						EngineData.ZoneStates.Relocated,
						Details.Part :: BasePart,
						OverlapParamaters
					)
				)
				--===============================================================================>
			end
			--=======================================================================================>
		end
		--==============================================================================================>
	end

	-- Function which will Remove the BoundsHandler's Evaluate function:

	function DetectionData.RemoveBoundsEvaluateFunction(self: DetectionHandler, TargetTypes: Targets.TargetTypes)
		-- Bind Bound Type Specific EvaluateCallbacks for easy runtime function calls:
		self._BoundsHandler.Evaluate = DO_NOTHING
		-- Clear the CurrentParts Array:
		self:RemoveCurrentParts()
	end

	-- Function ran every frame to evaluate detections:

	function DetectionData.Evaluate(self: DetectionHandler)
		--==============================================================================================>
		-- If the Detecting Variable is false then return from this function:
		if self.Detecting == false then
			return
		end
		-- If OverlapParamaters are nil, return:
		if not self._OverlapParamaters then
			return
		end
		--==============================================================================================>

		-- Begin Profiling:
		debug.profilebegin("[Zoner]: [Complex]: Evaluate: BoundsHandler")

		-- Call Evaluate callback:
		self._BoundsHandler:Evaluate()

		-- End Profiling:
		debug.profileend()

		-- Begin Profiling:
		debug.profilebegin("[Zoner]: [Complex]: Evaluate: TargetHandlers")

		for Target, TargetHandler: Targets.TargetHandler in self._TargetHandlers do
			--========================================================================================>
			-- If the Target is of the Parts variety then:
			if Target == "Part" then
				-- Compute the Locations of the Parts:
				self:ComputePartLocations(TargetHandler)
			else
				-- Loop through all the Objects/Items being stored in the Current Map in the Target Handler.
				-- Check if TargetHandler currently has a Tracker associated with that TrackerItem's Key,
				-- The Key should be the same Key used to store the Tracker Object

				-- If No Tracker is present for the TrackerItem stored in current, then we need to add it to be exited from the Zone
				-- If a Tracker is present, but its ZoneIdMap is Clear for this Zone, then we need to clear from Current and Exit Zone:
				for TrackerKey: any, TrackerItem: any in TargetHandler:GetCurrent() do
					if
						not TargetHandler:GetTrackers()[TrackerKey]
						or TargetHandler:GetTrackers()[TrackerKey]:GetZoneIDMap()[EngineData.ZoneId] == nil
					then
						TargetHandler:AddToExited(TrackerItem)
					end
				end

				-- Loop through the TargetHandler's Tracker Dictionary and Compute the Location for each Tracker individualy:
				-- Also use the Reused_HitTargetParts Dictionary to narrow down the Tracker's Parts:
				for Key: any, Tracker in TargetHandler:GetTrackers() do
					-- Pass in the Array consisting of only the Parts detected in CurrentParts that are apart of this Tracked Object:
					self:ComputeTrackerLocation(
						Key,
						TargetHandler,
						Tracker,
						Tracker:GetTargetPartsFromHitParts(self._CurrentParts, TargetHandler.Reused_HitTargetParts)
					)
					-- Clear the HitTargetParts table after its filled:
					table.clear(TargetHandler.Reused_HitTargetParts)
				end

				-- Loop through the Entered Values and add each to the Current:
				for Index: number, Value: any in ipairs(TargetHandler:GetEntered()) do
					TargetHandler:AddToCurrent(Value)
				end
				-- Loop through the Exited Values and remove each from the Current:
				for Index: number, Value: any in ipairs(TargetHandler:GetExited()) do
					TargetHandler:RemoveFromCurrent(Value)
				end
			end
			--========================================================================================>
		end

		-- End Profiling:
		debug.profileend()

		-- Clear the CurrentParts Array:
		self:RemoveCurrentParts()

		--===============================================================================>
	end

	--=======================================================================================================>

	-- Return the DetectionHandler Object:
	return DetectionData :: DetectionHandler

	--=======================================================================================================>
end

-- Constructor function that will create a "Simple" DetectionHandler and return the Object after inheriting from "Default":
DetectionHandlers[Enums.DetectionMethod.ENUMS.Simple].New = function(EngineData: ZoneEngineData): DetectionHandler
	--=======================================================================================================>

	-- Set Memory Category:
	debug.setmemorycategory("[Zoner]: Detection")

	-- Define the TargetData and Inherit from the Base Class:
	local DetectionData: DetectionHandler = DetectionHandler(EngineData) :: DetectionHandler

	--=======================================================================================================>

	-- Function which will Add the BoundsHandler's Evaluate function:
	function DetectionData.AddBoundsEvaluateFunction(self: DetectionHandler, TargetTypes: Targets.TargetTypes)
		--==============================================================================================>
		-- If no OverlapParams, return:
		if not self._OverlapParamaters then
			return
		end

		-- if the BoundsHandler Evaluate function is already set, and the TargetTypes is not Part, return:
		if self._BoundsHandler.Evaluate ~= DO_NOTHING and TargetTypes ~= "Part" then
			return
		end

		-- Local reference for less indexing:
		-- If Part is the target type, we will make the Params GRAB everything, vs Player Include list:
		local OverlapParamaters: OverlapParams = if TargetTypes == "Part"
			then self._OverlapParamaters.PartsExcludeList
			else self._OverlapParamaters.PartsExcludeList

		-- Bind Bound Type Specific EvaluateCallbacks for easy runtime function calls:
		if self._BoundsHandler:GetBoundType() == "PerPart" then
			--================================================================================================>
			-- Set an EvaluateCallback:
			self._BoundsHandler.Evaluate = function(BoundsHandler: Bounds.BoundsHandler)
				--=======================================================================================>
				-- Loop through the ZoneParts that make up the Zone:
				for Key, Details in BoundsHandler:GetZonePieceDetailsMap() do
					--===============================================================================>
					-- Get the Results of the Inidividual Part of the Zone:
					-- Loop through the Results from the Single Part of the Zone, and Check to make sure each Part is not already in the
					-- Global Zone Results Table, if its not already added to the Results Array, Insert it to combine the zone parts:
					DetectionData:AddToCurrentParts(
						WorldModel:GetPartBoundsInBox(
							EngineData.ZoneStates.Relocated,
							Details.CFrame or Details.Piece.CFrame,
							Details.Size,
							OverlapParamaters
						)
					)
					--===============================================================================>
				end
				--=======================================================================================>
			end
			--================================================================================================>
		else
			--================================================================================================>
			-- Set an EvaluateCallback:
			self._BoundsHandler.Evaluate = function(BoundsHandler: Bounds.BoundsHandler)
				--=======================================================================================>
				-- Get the Results of the Inidividual Part of the Zone:
				-- Loop through the Results from the Single Part of the Zone, and Check to make sure each Part is not already in the
				-- Global Zone Results Table, if its not already added to the Results Array, Insert it to combine the zone parts:
				DetectionData:AddToCurrentParts(
					WorldModel:GetPartBoundsInBox(
						EngineData.ZoneStates.Relocated,
						BoundsHandler.ZoneBoxData.CFrame,
						BoundsHandler.ZoneBoxData.Size,
						OverlapParamaters
					)
				)
				--=======================================================================================>
			end
			--================================================================================================>
		end

		--==============================================================================================>
	end

	-- Function which will Remove the BoundsHandler's Evaluate function:
	function DetectionData.RemoveBoundsEvaluateFunction(self: DetectionHandler, TargetTypes: Targets.TargetTypes)
		-- Bind Bound Type Specific EvaluateCallbacks for easy runtime function calls:
		self._BoundsHandler.Evaluate = DO_NOTHING
		-- Clear the CurrentParts Array:
		self:RemoveCurrentParts()
	end

	-- Function ran every frame to evaluate detections:
	function DetectionData.Evaluate(self: DetectionHandler)
		--==============================================================================================>
		-- If the Detecting Variable is false then return from this function:
		if self.Detecting == false then
			return
		end
		--==============================================================================================>

		-- Begin Profiling:
		debug.profilebegin("[Zoner]: [Simple]: Evaluate: BoundsHandler")

		-- Call Evaluate callback:
		self._BoundsHandler:Evaluate()

		-- End Profiling:
		debug.profileend()

		-- Begin Profiling:
		debug.profilebegin("[Zoner]: [Simple]: Evaluate: TargetHandlers")

		for Target, TargetHandler: Targets.TargetHandler in self._TargetHandlers do
			--========================================================================================>
			-- If the Target is of the Parts variety then:
			if Target == "Part" then
				-- Compute the Locations of the Parts:
				self:ComputePartLocations(TargetHandler)
			else
				-- Loop through all the Objects/Items being stored in the Current Map in the Target Handler.
				-- Check if TargetHandler currently has a Tracker associated with that TrackerItem's Key,
				-- The Key should be the same Key used to store the Tracker Object

				-- If No Tracker is present for the TrackerItem stored in current, then we need to add it to be exited from the Zone
				-- If a Tracker is present, but its ZoneIdMap is Clear for this Zone, then we need to clear from Current and Exit Zone:
				for TrackerKey: any, TrackerItem: any in TargetHandler:GetCurrent() do
					if
						not TargetHandler:GetTrackers()[TrackerKey]
						or TargetHandler:GetTrackers()[TrackerKey]:GetZoneIDMap()[EngineData.ZoneId] == nil
					then
						TargetHandler:AddToExited(TrackerItem)
					end
				end

				-- Loop through the TargetHandler's Tracker Dictionary and Compute the Location for each Tracker individualy:
				-- Also use the Reused_HitTargetParts Dictionary to narrow down the Tracker's Parts:
				for Key: string, Tracker in TargetHandler:GetTrackers() do
					-- Pass in the Array consisting of only the Parts detected in CurrentParts that are apart of this Tracked Object:
					self:ComputeTrackerLocation(
						Key,
						TargetHandler,
						Tracker,
						Tracker:GetTargetPartsFromHitParts(self._CurrentParts, TargetHandler.Reused_HitTargetParts)
					)
					-- Clear the HitTargetParts table after its filled:
					table.clear(TargetHandler.Reused_HitTargetParts)
				end

				-- Loop through the Entered Values and add each to the Current:
				for Index: number, Value: any in ipairs(TargetHandler:GetEntered()) do
					TargetHandler:AddToCurrent(Value)
				end
				-- Loop through the Exited Values and remove each from the Current:
				for Index: number, Value: any in ipairs(TargetHandler:GetExited()) do
					TargetHandler:RemoveFromCurrent(Value)
				end
			end
			--========================================================================================>
		end

		-- End Profiling:
		debug.profileend()

		-- Clear the CurrentParts Array:
		self:RemoveCurrentParts()

		--===============================================================================>
	end

	--=======================================================================================================>

	-- Return the DetectionHandler Object:
	return DetectionData :: DetectionHandler

	--=======================================================================================================>
end

-- Constructor function that will create a "Efficient" DetectionHandler and return the Object after inheriting from "Default":
DetectionHandlers[Enums.DetectionMethod.ENUMS.Efficient].New = function(EngineData: ZoneEngineData): DetectionHandler
	--=======================================================================================================>

	-- Set Memory Category:
	debug.setmemorycategory("[Zoner]: Detection")

	-- Define the TargetData and Inherit from the Base Class:
	local DetectionData: DetectionHandler = DetectionHandler(EngineData) :: DetectionHandler

	--=======================================================================================================>

	-- Function which will Add the BoundsHandler's Evaluate function:
	function DetectionData.AddBoundsEvaluateFunction(self: DetectionHandler, TargetTypes: Targets.TargetTypes)
		--==============================================================================================>
		-- If no OverlapParams, return:
		if not self._OverlapParamaters then
			return
		end

		-- if the BoundsHandler Evaluate function is already set, and the TargetTypes is not Part, return:
		if self._BoundsHandler.Evaluate ~= DO_NOTHING and TargetTypes ~= "Part" then
			return
		end

		-- Local reference for less indexing:
		-- If Part is the target type, we will make the Params GRAB everything, vs Player Include list:
		local OverlapParamaters: OverlapParams = if TargetTypes == "Part"
			then self._OverlapParamaters.PartsExcludeList
			else self._OverlapParamaters.PartsExcludeList

		-- Bind Bound Type Specific EvaluateCallbacks for easy runtime function calls:
		if self._BoundsHandler:GetBoundType() == "PerPart" then
			--================================================================================================>
			-- Set an EvaluateCallback:
			self._BoundsHandler.Evaluate = function(BoundsHandler: Bounds.BoundsHandler)
				--=======================================================================================>
				-- Loop through the ZoneParts that make up the Zone:
				for Key, Details in BoundsHandler:GetZonePieceDetailsMap() do
					--===============================================================================>
					-- Get the Results of the Inidividual Part of the Zone:
					-- Loop through the Results from the Single Part of the Zone, and Check to make sure each Part is not already in the
					-- Global Zone Results Table, if its not already added to the Results Array, Insert it to combine the zone parts:
					DetectionData:AddToCurrentParts(
						WorldModel:GetPartBoundsInBox(
							EngineData.ZoneStates.Relocated,
							Details.CFrame or Details.Piece.CFrame,
							Details.Size,
							OverlapParamaters
						)
					)
					--===============================================================================>
				end
				--=======================================================================================>
			end
			--================================================================================================>
		else
			--================================================================================================>
			-- Set an EvaluateCallback:
			self._BoundsHandler.Evaluate = function(BoundsHandler: Bounds.BoundsHandler)
				--=======================================================================================>
				-- Get the Results of the Inidividual Part of the Zone:
				-- Loop through the Results from the Single Part of the Zone, and Check to make sure each Part is not already in the
				-- Global Zone Results Table, if its not already added to the Results Array, Insert it to combine the zone parts:
				DetectionData:AddToCurrentParts(
					WorldModel:GetPartBoundsInBox(
						EngineData.ZoneStates.Relocated,
						BoundsHandler.ZoneBoxData.CFrame,
						BoundsHandler.ZoneBoxData.Size,
						OverlapParamaters
					)
				)
				--=======================================================================================>
			end
			--================================================================================================>
		end

		--==============================================================================================>
	end

	-- Function which will Remove the BoundsHandler's Evaluate function:
	function DetectionData.RemoveBoundsEvaluateFunction(self: DetectionHandler, TargetTypes: Targets.TargetTypes)
		-- Bind Bound Type Specific EvaluateCallbacks for easy runtime function calls:
		self._BoundsHandler.Evaluate = DO_NOTHING
		-- Clear the CurrentParts Array:
		self:RemoveCurrentParts()
	end

	-- Function ran every frame to evaluate detections:
	function DetectionData.Evaluate(self: DetectionHandler)
		--==============================================================================================>
		-- If the Detecting Variable is false then return from this function:
		if self.Detecting == false then
			return
		end

		-- Begin Profiling:
		debug.profilebegin("[Zoner]: [Efficient]: Evaluate: BoundsHandler")

		-- Call Evaluate callback:
		self._BoundsHandler:Evaluate()

		-- End Profiling:
		debug.profileend()

		-- Begin Profiling:
		debug.profilebegin("[Zoner]: [Efficient]: Evaluate: TargetHandlers")

		for Target, TargetHandler: Targets.TargetHandler in self._TargetHandlers do
			--========================================================================================>
			-- If the Target is of the Parts variety then continue:
			if Target == "Part" then
				-- Compute the Locations of the Parts:
				self:ComputePartLocations(TargetHandler)
				-- Clear the CurrentParts Array:
				self:RemoveCurrentParts()
			else
				-- Loop through all the Objects/Items being stored in the Current Map in the Target Handler.
				-- Check if TargetHandler currently has a Tracker associated with that TrackerItem's Key,
				-- The Key should be the same Key used to store the Tracker Object

				-- If No Tracker is present for the TrackerItem stored in current, then we need to add it to be exited from the Zone
				-- If a Tracker is present, but its ZoneIdMap is Clear for this Zone, then we need to clear from Current and Exit Zone:
				for TrackerKey: any, TrackerItem: any in TargetHandler:GetCurrent() do
					if
						not TargetHandler:GetTrackers()[TrackerKey]
						or TargetHandler:GetTrackers()[TrackerKey]:GetZoneIDMap()[EngineData.ZoneId] == nil
					then
						TargetHandler:AddToExited(TrackerItem)
					end
				end

				-- Loop through the TargetHandler's Tracker Dictionary and Compute the Location for each Tracker individualy:
				-- Also use the Reused_HitTargetParts Dictionary to narrow down the Tracker's Parts:
				for Key: string, Tracker in TargetHandler:GetTrackers() do
					-- Compute the Location of the passed in Tracker:
					self:ComputeTrackerLocation(Key, TargetHandler, Tracker)
				end

				-- Loop through the Entered Values and add each to the Current:
				for Index: number, Value: any in ipairs(TargetHandler:GetEntered()) do
					TargetHandler:AddToCurrent(Value)
				end
				-- Loop through the Exited Values and remove each from the Current:
				for Index: number, Value: any in ipairs(TargetHandler:GetExited()) do
					TargetHandler:RemoveFromCurrent(Value)
				end
			end
			--========================================================================================>
		end

		-- End Profiling:
		debug.profileend()

		--===============================================================================>
	end

	--=======================================================================================================>

	-- Return the DetectionHandler Object:
	return DetectionData :: DetectionHandler

	--=======================================================================================================>
end

--===========================================================================================================================>

-- Called from the Parent running this Module, to update some global scope:
function DetectionHandlers.UpdateGlobalScope(ZonerHolder: ZoneInstances.ZonerHolder)
	Targets.UpdateGlobalScope(ZonerHolder)
end

--===========================================================================================================================>

-- Freeze subtables:
table.freeze(DetectionHandlers[Enums.DetectionMethod.ENUMS.Complex])
table.freeze(DetectionHandlers[Enums.DetectionMethod.ENUMS.Simple])
table.freeze(DetectionHandlers[Enums.DetectionMethod.ENUMS.Efficient])

--===========================================================================================================================>

-- Return a Frozen Module Table:
return table.freeze(DetectionHandlers) :: typeof(DetectionHandlers)

--===========================================================================================================================>


--===========================================================================================================================>
--!optimize 2
--!strict
--===========================================================================================================================>

-- Set Memory Category:
debug.setmemorycategory('[Zone]: Engine')

-- Define Module table
local Engine = {}

--===========================================================================================================================>
--[ SERVICES: ]

-- Get the needed Services for the following Code:
local CollectionService = game:GetService('CollectionService')
local RunService        = game:GetService('RunService')

--===========================================================================================================================>
--[ GLOBALS: ]

-- [ Global Dependencies: ]

local MiscHelpers = require(`../../Utility/MiscHelpers`);
local Helpers     = require(`../Zone/Helpers`)

-- [ Internals ]
local DetectionCoverage = require('../../Data/Enums/DetectionCoverage')
local DetectionMethod   = require('../../Data/Enums/DetectionMethod')
local DetectionMode     = require('../../Data/Enums/DetectionMode')
local Simulation        = require('../../Data/Enums/Simulation')
local Execution         = require('../../Data/Enums/Execution')
local Bounds            = require('../../Data/Enums/Bounds')
local Rate              = require('../../Data/Enums/Rate')

local RateConfig        = require('../../Data/Config/RateConfig')

-- [ Local Dependencies: ]
local Detections = require(`@self/Detections`);

--===========================================================================================================================>
--[ CONSTANTS: ]

-- RANDOM GENERATOR:
local RANDOM = Random.new();

-- The RunContext of the Module:
local RUN_CONTEXT: 'Client'|'Server' = if RunService:IsServer() then 'Server' else 'Client'

-- Create a Enums table for easier lookup:
local ENUMS = {
	DetectionCoverage = DetectionCoverage;
	DetectionMethod   = DetectionMethod;
	DetectionMode     = DetectionMode;
	Simulation        = Simulation;
	Execution         = Execution;
	Bounds            = Bounds;
	Rate              = Rate;
}

--===========================================================================================================================>
--[ TYPES: ]

-- [ Require Types: ]

-- This will inject all types into this context.
local ZonePrimitives = require('../../Types/ZonePrimitives')
local ZoneInstances  = require('../../Types/ZoneInstances')
local ZoneTargets    = require('../../Types/ZoneTargets')
local ZoneConfig     = require('../../Types/ZoneConfig')
local ZoneState      = require('../../Types/ZoneState')

-- [ Register Types: ]

-- Signal function for direct callback to the zone object:
type ZoneSignalFunction = ((Purpose: string, ...any) -> ())

-- Create and Export the Module's Object Type:
export type Engine = typeof(setmetatable({} :: {
	--======================================>
	_Identifier:    string;
	_Container:     ZonePrimitives.ZoneContainer;
	_ContainerType: ZonePrimitives.ZoneContainerType;

	_Connections: {[string]: RBXScriptConnection};

	_ZoneFolder:    ZoneInstances.ZoneFolder;
	--======================================>
	_ActiveTargets: ZoneTargets.ZoneActiveTargetsTable;
	_ActiveSignals: ZoneTargets.ZoneActiveSignalsTable;
	_Config:        ZoneConfig.ZoneConfigTable;
	_States:        ZoneState.ZoneStatesTable;
	--====================================================>
	_DetectionHandler: Detections.DetectionHandler;
	--======================================>
	_Tags: {ZonePart: string; Holder: string };

	_Instances: {
		Holders:   {Instance};
		ZoneParts: {BasePart};
	};

	_Counters: {
		EvaluateParallel: {Counter: number; CounterMax: number};
		EvaluateSerial:   {Counter: number; CounterMax: number};
	};
	--======================================>
	-- Meta Indexing:

	-- Whether the Zone has Connections:
	Active: boolean;

	_Holders:   {Instance};
	_ZoneBoxes: ZonePrimitives.ZoneBoxes;
	_ZoneParts: {BasePart};

	-- Added via the Parent Zone Object on SERIAL Objects only:
	FireSignal: ((Purpose: string, ...any) -> ())?;
	--======================================>
}, {} :: typeof(Engine)))

--===========================================================================================================================>
--[ LOCAL FUNCTIONS: ]

local function Initialize(Engine: Engine)
	--=======================================================================================================>

	-- If the Execution Config is Parallel to use Parallel:
	-- Using this because 'Dynamic Property Access on Signals' is 'unsafe'
	local UseParallel = Engine._Config.Execution == Execution.ENUMS.Parallel

	--=======================================================================================================>

	-- Reference the Folder Instance:
	local ActiveSignals = Engine._ZoneFolder.ActiveSignals
	-- Index the Propert Connection Function/Signal based on 'UserParallel'
	local AC_ActiveSignals_Connect: ((RBXScriptSignal, (string) -> ()) -> RBXScriptConnection) =
		(if UseParallel then ActiveSignals.AttributeChanged.ConnectParallel else ActiveSignals.AttributeChanged.Connect) :: any

	-- Fire when any Attribute Changes on the ActiveTargets:
	Engine._Connections['AC_ActiveSignals'] = AC_ActiveSignals_Connect(ActiveSignals.AttributeChanged, function(Target: string)
		--================================================================================================>
		-- If already Destroyed, return:
		if Engine._States.Destroyed then return end
		-- Update this Objects Properties Attributes from the Changed Event firing:
		Engine._ActiveSignals[Target] = Engine._ZoneFolder.ActiveSignals:GetAttribute(Target)
		--================================================================================================>
	end)

	-- Reference the Folder Instance:
	local ActiveTargets = Engine._ZoneFolder.ActiveTargets
	-- Index the Propert Connection Function/Signal based on 'UserParallel'
	local AC_ActiveTargets_Connect: ((RBXScriptSignal, (string) -> ()) -> RBXScriptConnection) =
		(if UseParallel then ActiveTargets.AttributeChanged.ConnectParallel else ActiveTargets.AttributeChanged.Connect) :: any

	-- Fire when any Attribute Changes on the ActiveTargets:
	Engine._Connections['AC_ActiveTargets'] = AC_ActiveTargets_Connect(ActiveTargets.AttributeChanged, function(Target: string)
		--================================================================================================>
		-- If already Destroyed, return:
		if Engine._States.Destroyed then return end
		--================================================================================================>
		-- Update this Objects Properties Attributes from the Changed Event firing:
		Engine._ActiveTargets[Target] = Engine._ZoneFolder.ActiveTargets:GetAttribute(Target)
		--================================================================================================>
		-- Synchronize the thread:
		if UseParallel then task.synchronize() end
		--================================================================================================>
		-- If the Target is Active then Add the TargetHandler on the DetectionHandler, else Remove it from the DetectionHandler:
		if Engine._ActiveTargets[Target] then
			Engine._DetectionHandler:AddTargetHandler(Target :: any)
		else
			Engine._DetectionHandler:RemoveTargetHandler(Target :: any)
		end
		--================================================================================================>
	end)

	-- Reference the Folder Instance:
	local States = Engine._ZoneFolder.States
	-- Index the Propert Connection Function/Signal based on 'UserParallel'
	local AC_States_Connect: ((RBXScriptSignal, (string) -> ()) -> RBXScriptConnection) =
		(if UseParallel then States.AttributeChanged.ConnectParallel else States.AttributeChanged.Connect) :: any

	-- Fire when any Attribute Changes on the States:
	Engine._Connections['AC_States'] = AC_States_Connect(States.AttributeChanged, function(State: string)
		--================================================================================================>
		-- If already Destroyed, return:
		if Engine._States.Destroyed then return end
		--================================================================================================>
		-- Update this Objects Properties Attributes from the Changed Event firing:
		Engine._States[State] = Engine._ZoneFolder.States:GetAttribute(State)
		--================================================================================================>
		-- If we are in parallel syncrhonize to serial:
		if Engine._Config.Execution == Execution.ENUMS.Parallel then task.synchronize() end
		--================================================================================================>
		-- If the State is Visible, thenm call the Function for Toggling Visibility On and Off:
		if State == 'Visible' then Engine:SetVisibility(Engine._States[State]) end
		if State == 'Relocated' and Engine._States[State] == true then
			-- Synchronize the thread:
			if UseParallel then task.synchronize() end
			-- Call relocate on the bounds:
			Engine._DetectionHandler:GetBoundsHandler():Relocate()
		end
		if State == 'Paused' then
			Engine:SetSimulation(Engine._Config.Simulation, if Engine._States[State] == true then 'Off' else 'On')
		end
		if State == 'Active' then
			Engine:SetSimulation(Engine._Config.Simulation, if Engine._States[State] == false then 'Off' else 'On')
		end
		--================================================================================================>
	end)

	-- Reference the Folder Instance:
	local Config = Engine._ZoneFolder.Config
	-- Index the Propert Connection Function/Signal based on 'UserParallel'
	local AC_Config_Connect: ((RBXScriptSignal, (string) -> ()) -> RBXScriptConnection) =
		(if UseParallel then Config.AttributeChanged.ConnectParallel else Config.AttributeChanged.Connect) :: any

	-- Fire when any Attribute Changes on the Config:
	Engine._Connections['AC_Config'] = AC_Config_Connect(Config.AttributeChanged, function(Config: string)
		--================================================================================================>
		-- If already Destroyed, return:
		if Engine._States.Destroyed then return end
		--================================================================================================>
		-- Update this Objects Properties Attributes from the Changed Event firing:
		Engine._Config[Config] = Engine._ZoneFolder.Config:GetAttribute(Config)
		--================================================================================================>
		-- If the Config is the Detection, then call the Method for it:
		if string.gmatch(Config, 'Detection') then
			Engine:SetDetection(Engine._Config.DetectionCoverage, Engine._Config.DetectionMode, Engine._Config.DetectionMethod)
		end
		-- If the Config is the Simulation, then call the Method for it:
		if Config == 'Simulation' then Engine:SetSimulation(Engine._Config[Config], 'On') end
		-- If the Config is the Rate, then call the Method for it:
		if Config == 'Rate'       then Engine:SetRate(Engine._Config[Config])       end
		--================================================================================================>
	end)

	--=======================================================================================================>

	-- If the Engine is being Run in Parallel (on another actor) then
	-- Connect Events that cant be reached by the Parent Zone Object:
	if Engine._Config.Execution == Execution.ENUMS.Parallel then
		--=========================================================================================>

		-- Connect to the AncestryChanged event of the ZoneFolder:
		-- We then check if the ZoneFolder is still a decendent of the WorldModel, meaning it hasnt been destroyed.
		-- We do this to clear the Data in case the ZoneFolder is Destroyed:
		Engine._Connections['AC_ZoneFolder'] = Engine._ZoneFolder.AncestryChanged:ConnectParallel(function()
			--====================================================================================>
			if not Engine._ZoneFolder then return end
			-- If the Destroying Attribute is true on the ZoneFolder, then ignore the Ancestry Changed:
			if Engine._ZoneFolder:GetAttribute('Destroying') == true then return end
			if Engine._ZoneFolder.Parent == nil or Engine._ZoneFolder:IsDescendantOf(game) == false then
				print('Backup, Engine: Folder Ancestry Changed'); task.synchronize(); Engine:Destroy()
			end
			--====================================================================================>
		end)

		--=========================================================================================>

		-- If the Container Type is a Table of Box Bounds, then theres no Parts in this Zone to need Events For, so return from here:
		if Engine._ContainerType == 'Boxes' then return end

		--=========================================================================================>

		-- Connect to the ZonePart Tag Added Signal:
		-- Fires when a Part with the Zone Tag is added back to the Workspace:
		-- We will use this to reduce the Zone Based on Streaming:

		-- I made this ConnectParallel, theres a few things that run after this signal fires that need to be in serial,
		-- And i try to check if those are needing to be ran before switching back to serial, if the gain is very little,
		-- might switch this back to Connect serial:
		Engine._Connections['CS_ZonePart_Add'] =
			CollectionService:GetInstanceAddedSignal(Engine._Tags.ZonePart):ConnectParallel(function(ZonePart: BasePart)
				-- If Destroyed was already called then return:
				if not Engine.OnZonePartUpdate then return end
				Engine:OnZonePartUpdate('Add', ZonePart)
			end)

		-- Connect to the ZonePart Tag Removed Signal:
		-- Fires when a Part with the Zone Tag is removed from the Workspace:
		-- We will use this to restore the Zone Based on Streaming:
		Engine._Connections['CS_ZonePart_Remove'] =
			CollectionService:GetInstanceRemovedSignal(Engine._Tags.ZonePart):ConnectParallel(function(ZonePart: BasePart)
				-- If Destroyed was already called then return:
				if not Engine.OnZonePartUpdate then return end
				Engine:OnZonePartUpdate('Remove', ZonePart)
			end)

		-- Connect to the Holder Tag Added Signal:
		Engine._Connections['CS_Holder_Add'] =
			CollectionService:GetInstanceAddedSignal(Engine._Tags.Holder):ConnectParallel(function(Holder: Instance)
				-- If Destroyed was already called then return:
				if not Engine.OnHolderInstanceUpdate then return end
				Engine:OnHolderInstanceUpdate('Add', Holder)
			end)

		-- Connect to the Holder Tag Added Signal:
		Engine._Connections['CS_Holder_Remove'] =
			CollectionService:GetInstanceRemovedSignal(Engine._Tags.Holder):ConnectParallel(function(Holder: Instance)
				-- If Destroyed was already called then return:
				if not Engine.OnHolderInstanceUpdate then return end
				Engine:OnHolderInstanceUpdate('Remove', Holder)
			end)

		--=========================================================================================>
	end

	--=======================================================================================================>
end

--===========================================================================================================================>
--[ CONSTRUCTOR METHODS: ]

-- Constructor Function for this individual object:
function Engine.New(Id: string, Folder: ZoneInstances.ZoneFolder, Container: ZonePrimitives.ZoneContainer, SignalFunction: ZoneSignalFunction?): Engine
	--=======================================================================================================>

	-- Set a Memory Category for this Zoner:
	debug.setmemorycategory('[Zoner]: Engine')

	--=======================================================================================================>
	-- Define Data
	local EngineData: Engine = {
		--====================================================>
		-- Store the Id of the Zone:
		_Identifier = Id;
		-- Reference to the Original Zone Container:
		_Container = Container;
		_ContainerType = Helpers.GetZoneContainerType(Container) :: ZonePrimitives.ZoneContainerType;
		-- Reference to the ZoneFolder in the Zoner:
		_ZoneFolder = Folder;
		--====================================================>
		-- Dictionary of ZoneParts and their Properties:
		_Config = {};
		--====================================================>
		_Tags = {
			ZonePart = `{Id}:ZonePart:{RUN_CONTEXT}`;
			Holder   = `{Id}:Holder:{RUN_CONTEXT}`;
		};
		--====================================================>

		_Instances = {
			Holders   = {};
			ZoneParts = {};
		};

		_States = {};
		_ActiveTargets = {};
		_ActiveSignals = {};

		_Counters = {
			EvaluateParallel = {Counter = 0; CounterMax = 1};
			EvaluateSerial   = {Counter = 0; CounterMax = 1};
		};

		_Connections = {};
		--====================================================>
	} :: any

	--=======================================================================================================>

	-- Update each of the Folder Attribute Dictionaries by grabbing their attributes dynamically via the Array:
	for Index: number, FolderName: string in ipairs({'States', 'Config', 'ActiveTargets', 'ActiveSignals'}) do
		--================================================================================================>
		-- Find the Folder (Configuration) as a Child of the Actor using the Name String passed:
		local DataFolder: Configuration = EngineData._ZoneFolder:FindFirstChild(FolderName) :: Configuration
		-- Grab the Attributes on the Folders and update our copy of them:
		for Name: string, Value: any in DataFolder:GetAttributes() do
			if FolderName == 'Config' and typeof(Value) == 'number' then
				-- Convert the number back into a full Enum:
				EngineData[`_{FolderName}`][Name] = ENUMS[Name].HASH.Read[Value]
			else
				EngineData[`_{FolderName}`][Name] = Value
			end
		end
		--================================================================================================>
	end

	-- Construct a new Handler Object with the Trove and Set it in the Table:
	-- Index the Detection Specific Table with the DetectionMethod Name to gets its New Method:
	EngineData._DetectionHandler = Detections[EngineData._Config.DetectionMethod].New({
		ZoneContainer     = EngineData._Container;
		ZoneContainerType = EngineData._ContainerType;
		ZoneConfig        = EngineData._Config;
		ZoneStates        = EngineData._States;
		ZoneFolder        = EngineData._ZoneFolder;
		ZonePieces        = if EngineData._ContainerType == 'Boxes' then
			EngineData._Container :: ZonePrimitives.ZoneBoxes
			else
			EngineData._Instances.ZoneParts;
		-- Add the Zone Update bindable event if no Signal function was passed:
		ZoneSignalEvent    =
			if not SignalFunction then script:FindFirstAncestor('Modules').Parent:WaitForChild('Events'):WaitForChild('Zone_Update') else nil;
		-- Add the Signal Function:
		ZoneSignalFunction = SignalFunction;

		ZoneId            = EngineData._Identifier;
	})

	--=======================================================================================================>

	-- Set Metatable to the MetaTable and the current Module
	setmetatable(EngineData :: any, Engine)

	--=======================================================================================================>

	-- If the Container Type is a Table of Box Bounds, then theres no Parts in this Zone to need Events For, so return from here:
	if EngineData._ContainerType ~= 'Boxes' then
		-- Check the CollectionService Tags for the ZoneParts already tagged:
		for Index: number, Part in ipairs(CollectionService:GetTagged(EngineData._Tags.ZonePart)) do
			EngineData:OnZonePartUpdate('Add', Part)
		end
		-- Check the CollectionService Tags for the Holders already tagged:
		for Index: number, Holder in ipairs(CollectionService:GetTagged(EngineData._Tags.Holder)) do
			EngineData:OnHolderInstanceUpdate('Add', Holder)
		end
	end

	--=======================================================================================================>

	-- Start the Inventory:
	Initialize(EngineData)

	-- Update the Rate Counter with the Config:
	EngineData:SetRate(EngineData._Config.Rate)
	-- Update the Detection with the Config:
	EngineData:SetDetection(EngineData._Config.DetectionCoverage, EngineData._Config.DetectionMode, EngineData._Config.DetectionMethod)
	-- Update the Simulation Events with the Config:
	EngineData:SetSimulation(EngineData._Config.Simulation, 'On')

	-- If Relocated is already true, then call Relocate on the BoundsHandler:
	if EngineData._States.Relocated then
		EngineData._DetectionHandler:GetBoundsHandler():Relocate()
	end

	-- Update the Visiblity with the State:
	EngineData:SetVisibility(EngineData._States.Visible)

	--=======================================================================================================>

	-- Loop through the ActiveTargets and Create a TargetHandler for each one accordingly:
	for Target, State: boolean in pairs(EngineData._ActiveTargets) do
		if State then EngineData._DetectionHandler:AddTargetHandler(Target) else EngineData._DetectionHandler:RemoveTargetHandler(Target) end
	end

	--=======================================================================================================>

	-- Return the MetaTable Data
	return EngineData :: any

	--=======================================================================================================>
end

-- Destroyer Function which clears the entirity of the Data for the Object:
function Engine.Destroy(self: Engine)
	--=======================================================================================================>
	-- If Destroyed was already called then return:
	if self._States.Destroyed then return end
	-- Set the Destroyed State to true:
	self._States.Destroyed = true
	--=======================================================================================================>
	-- Clear all self data:
	for Key, Connection in pairs(self._Connections) do self._Connections[Key]:Disconnect() end
	table.clear(self._Connections)

	self._DetectionHandler:Destroy()
	rawset(self :: any, '_DetectionHandler', nil)

	-- Clear all self data:
	for Index, Data in pairs(self) do self[Index] = nil end
	-- Set the Metatable to nil
	setmetatable(self :: any, nil)
	--=======================================================================================================>
end

--===========================================================================================================================>
--[ CONFIG UPDATE METHODS: ]

-- Function that is called when the Detection Config is updated:
function Engine.SetDetection(
	self: Engine,
	DetectionCoverage: DetectionCoverage.DetectionCoverageEnum,
	DetectionMode:     DetectionMode.DetectionModeEnum,
	DetectionMethod:   DetectionMethod.DetectionMethodEnum?
)
	self._DetectionHandler:UpdateDetectionCoverage()
end

-- Function that is called when the Simulation Config is updated:
function Engine.SetSimulation(self: Engine, Simulation: Simulation.SimulationEnum, Status: 'On'|'Off')
	--=======================================================================================================>
	-- If ManualStepping is true then we do not connect the internal Simulation:
	if self._Config.ManualStepping == true then return end
	-- Synchronize the thread:
	if self._Config.Execution == Execution.ENUMS.Parallel then task.synchronize() end
	--=======================================================================================================>
	-- Destroy all the Current Simulation Events so that we can recreate them on a new Event:
	if self._Connections.Simulation_EvaluateParallel then
		self._Connections.Simulation_EvaluateParallel:Disconnect()
		self._Connections.Simulation_EvaluateParallel = nil :: any;
	end
	-- Destroy all the Current Simulation Events so that we can recreate them on a new Event:
	if self._Connections.Simulation_EvaluateSerial then
		self._Connections.Simulation_EvaluateSerial:Disconnect()
		self._Connections.Simulation_EvaluateSerial = nil :: any;
	end
	--=======================================================================================================>
	-- If Status is Off, we just Disconnect and Clear Connection if its initialized:
	if Status == 'Off' then return end
	--=======================================================================================================>
	-- Dynamically Index the RunService Event using the Name of the Simulation Config Chose: (PostSimulation, PreSimulation etc)
	local RunServiceSignal: RBXScriptSignal = RunService[Simulation.Name]
	--=======================================================================================================>
	-- Whether the use Parallel or Serial Connection:
	local UseParallel = self._Config.Execution == Execution.ENUMS.Parallel

	-- If UseParallel is true, then we will connect a serial and parallel service event, else, run them both in Serial:
	if UseParallel then
		-- Connect the Simulation Event Dynamically:
		self._Connections.Simulation_EvaluateParallel = RunServiceSignal.ConnectParallel(RunServiceSignal, function(DeltaTime: number)
			--==============================================================================>
			-- If the Counter is not at max, return to allow for varied update checking/polling:
			-- Checks every number interval as set in the Counters Table.
			if MiscHelpers.RateLimiter(self._Counters.EvaluateParallel, DeltaTime) then self:EvaluateParallel(DeltaTime) end
			--==============================================================================>
		end)

		-- MAYBE ADD FOR PART FILTERING IN OVERLAP PARAMS:

		-- Connect the Simulation Event Dynamically:
		--self._Connections.Simulation_EvaluateSerial = RunServiceSignal.Connect(RunServiceSignal, function(DeltaTime: number)
		--	--==============================================================================>
		--	-- If the Counter is not at max, return to allow for varied update checking/polling:
		--	-- Checks every number interval as set in the Counters Table.
		--	if MiscHelpers.RateLimiter(self._Counters.EvaluateSerial, DeltaTime) then self:EvaluateSerial(DeltaTime) end
		--	--==============================================================================>
		--end)

	else
		-- Connect the Simulation Event Dynamically:
		self._Connections.Simulation_EvaluateSerial = RunServiceSignal.Connect(RunServiceSignal, function(DeltaTime: number)
			--==============================================================================>
			-- If the Counter is not at max, return to allow for varied update checking/polling:
			-- Checks every number interval as set in the Counters Table.
			if MiscHelpers.RateLimiter(self._Counters.EvaluateParallel, DeltaTime) then self:EvaluateParallel(DeltaTime) end
			if MiscHelpers.RateLimiter(self._Counters.EvaluateSerial, DeltaTime)   then self:EvaluateSerial(DeltaTime)   end
			--==============================================================================>
		end)
	end

	--=======================================================================================================>
end

-- Function that is called when the Rate Config is updated:
function Engine.SetRate(self: Engine, Rate: Rate.RateEnum)
	-- Does the second Counter value as a random number from 0 - to the max counter value, so that Runs can be offset:
	self._Counters.EvaluateSerial.CounterMax,   self._Counters.EvaluateSerial.Counter   =
		RateConfig[Rate], RANDOM:NextInteger(0, RateConfig[Rate])
	-- Does the second Counter value as a random number from 0 - to the max counter value, so that Runs can be offset:
	self._Counters.EvaluateParallel.CounterMax, self._Counters.EvaluateParallel.Counter =
		RateConfig[Rate], RANDOM:NextInteger(0, RateConfig[Rate])
end

-- Method called when the Visiblity State Changes:
function Engine.SetVisibility(self: Engine, State: boolean)
	-- Call function on BoundsHandler:
	self._DetectionHandler:GetBoundsHandler():ToggleVisibility(State)
end

--===========================================================================================================================>

-- @Private
-- Method called when a ZonePart tag is added or removed:
function Engine.OnZonePartUpdate(self: Engine, Purpose: 'Add'|'Remove', ZonePart: BasePart)
	--=======================================================================================================>
	-- Boolean on whether the ZonePart is stored or not in the Dictionary:
	local ZonePartStoreIndex: number? = table.find(self._Instances.ZoneParts, ZonePart)
	-- If the Purpose is 'Remove', then remove the Part, else add it:
	if Purpose == 'Remove' then
		--===============================================================================================>
		-- If one is found, then Remove it from the Array:
		if ZonePartStoreIndex then
			--================================================================>
			-- Remove the ZonePart from the Array:
			table.remove(self._Instances.ZoneParts, ZonePartStoreIndex)
			-- Call the RemoveZonePart function from whatever BoundsHandler Object is stored:
			-- Removes the ZonePart and its Details from its Internal Object Data:
			self._DetectionHandler:GetBoundsHandler():RemoveZonePiece(ZonePart)
			--================================================================>
		else return end
		--===============================================================================================>
	else
		--===============================================================================================>
		-- If one is not found, then Add it to the Array:
		if not ZonePartStoreIndex then
			--================================================================>
			-- Store the ZonePart in an Array:
			table.insert(self._Instances.ZoneParts, ZonePart)
			-- Call the AddZonePart function from whatever BoundsHandler Object is stored:
			-- Adds the ZonePart and its Details to its Internal Object Data:
			self._DetectionHandler:GetBoundsHandler():AddZonePiece(ZonePart)
			--================================================================>
		else return end
		--===============================================================================================>
	end
	--=======================================================================================================>
end

-- @Private
-- Initialization function to start/setup the Object's initial data:
function Engine.OnHolderInstanceUpdate(self: Engine, Purpose: 'Add'|'Remove', Holder: Instance)
	--=======================================================================================================>
	-- If the Purpose is 'Remove', then remove the Part, else add it:
	if Purpose == 'Remove' then
		--===============================================================================================>
		-- Find the Index of the Holder in the Array:
		local HolderIndex: number? = table.find(self._Instances.Holders, Holder)
		-- If one is found, then Remove it from the Array:
		-- Remove the Part located at the Index from the Array:
		-- Return because theres nothing to update:
		if HolderIndex then table.remove(self._Instances.Holders, HolderIndex) else return end
		--===============================================================================================>
	else
		--===============================================================================================>
		-- If one is not found, then Add it to the Array:
		-- Insert the Holder into the Array:
		-- Return because theres nothing to update:
		if not table.find(self._Instances.Holders, Holder) then table.insert(self._Instances.Holders, Holder) else return end
		--===============================================================================================>
	end
	--=======================================================================================================>
end

--===========================================================================================================================>

-- Step Function for Zone Calculations:
function Engine.EvaluateSerial(self: Engine, DeltaTime: number)
	--=======================================================================================================>
	-- do something that loops through all the targets trackers and checks a
	-- boolean that says whether their parts have changed and then update the array only then

	--if self._TargetHandlers.Players then

	--	local FilterIncludeArray = {}

	--	-- Loop through the CurrentPartsInZone:
	--	for Name: string, Tracker in self._TargetHandlers.Players.Trackers do
	--		Tracker:FillFilterArray(FilterIncludeArray)
	--	end

	--	self._OverlapParamaters.PartsIncludeList.FilterDescendantsInstances = FilterIncludeArray

	--end

	--=======================================================================================================>
end

-- Step Function for Zone Calculations:
function Engine.EvaluateParallel(self: Engine, DeltaTime: number)
	--=======================================================================================================>
	-- Begin Profiling:
	debug.profilebegin('[Zoner]: Engine Evaluate')
	-- Run the Target Detection logic by the Zone:
	self._DetectionHandler:Evaluate()
	-- End Profiling:
	debug.profileend()
	-- Begin Profiling:
	debug.profilebegin('[Zoner]: Engine FireSignals')
	-- Fire Signals for the Detected:
	self._DetectionHandler:FireSignals(self._ActiveSignals)
	-- End Profiling:
	debug.profileend()
	--=======================================================================================================>
end

--===========================================================================================================================>
--[ INDEXER FUNCTIONS: ]

-- Create the MetaIndex function:
function Engine.__index(self: Engine, Index: string): any
	--=======================================================================================================>
	-- Specific Indexing:
	--=======================================================================================================>
	if Index == 'Container' then return self._Container end
	-- Return a ZoneBoxes Index which is just the Container if the Container Type is Table Of Boxes:
	if Index == '_ZoneBoxes' then return (if self._ContainerType == 'Boxes' then self._Container else nil) end
	if Index == '_ZoneParts' then return self._Instances.ZoneParts end
	if Index == '_Holders' then   return self._Instances.Holders end
	--=======================================================================================================>
	if Index == 'Active' then return self._States.Active end
	--=======================================================================================================>
	-- If Index is in the immediate Module tree, return that value:
	if Engine[Index] then return Engine[Index] end
	--=======================================================================================================>
	-- Return False if all else fails!
	return false
	--=======================================================================================================>
end

-- Create the New Index function:
function Engine.__newindex(self: Engine, Index: string, Value: any)
	error(`"{Index}" cannot be added to Engine`)
end

--===========================================================================================================================>

-- Called from the Actor running this Module, to update some global scope:
function Engine.UpdateGlobalScope(ZonerHolder: ZoneInstances.ZonerHolder)
	Detections.UpdateGlobalScope(ZonerHolder)
end

--===========================================================================================================================>

-- Return a Frozen Module Table:
return table.freeze({New = Engine.New, UpdateGlobalScope = Engine.UpdateGlobalScope})

--===========================================================================================================================>