--[[ Reference extension ]]
--

do
	local ReferenceTypes = {
		Character = {},
		CharacterPart = {}
	}

	local References = {} 
	local Objects = {}

	for i,v in pairs(ReferenceTypes) do
		References[i] = {}
		Objects[i] = {}
	end
	
	function Network:AddReference(key, refType, ...)
		local refInfo = ReferenceTypes[refType]
		assert(refInfo, "Invalid Reference Type")
		
		local refData = {
			Type = refType,
			Reference = key,
			Objects = {...},
			Aliases = {}
		}
		
		References[refType][refData.Reference] = refData
		
		local last = Objects[refType]
		for _,obj in ipairs(refData.Objects) do
			local list = last[obj] or {}
			last[obj] = list
			last = list
		end
		
		last.__Data = refData
	end

	function Network:AddReferenceAlias(key, refType, ...)
		local refInfo = ReferenceTypes[refType]
		assert(refInfo, "Invalid Reference Type")
		
		local refData = References[refType][key]
		if not refData then
			warn("Tried to add an alias to a non-existing reference")
			return
		end
		
		local objects = {...}
		refData.Aliases[#refData.Aliases + 1] = objects
		
		local last = Objects[refType]
		for _,obj in ipairs(objects) do
			local list = last[obj] or {}
			last[obj] = list
			last = list
		end
		
		last.__Data = refData
	end

	function Network:RemoveReference(key, refType)
		local refInfo = ReferenceTypes[refType]
		assert(refInfo, "Invalid Reference Type")
		
		local refData = References[refType][key]
		if not refData then
			warn("Tried to remove a non-existing reference")
			return
		end
		
		References[refType][refData.Reference] = nil
		
		local function rem(parent, objects, index)
			if index <= #objects then
				local key = objects[index]
				local child = parent[key]
				
				rem(child, objects, index + 1)
				
				if next(child) == nil then
					parent[key] = nil
				end
			elseif parent.__Data == refData then
				parent.__Data = nil
			end
		end
		
		local objects = Objects[refData.Type]
		rem(objects, refData.Objects, 1)
		
		for i,alias in ipairs(refData.Aliases) do
			rem(objects, alias, 1)
		end
	end

	function Network:GetObject(ref, refType)
		assert(ReferenceTypes[refType], "Invalid Reference Type")
		
		local refData = References[refType][ref]
		if not refData then
			return nil
		end
		
		return unpack(refData.Objects)
	end

	function Network:GetReference(...)
		local objects = {...}
		
		local refType = table.remove(objects)
		assert(ReferenceTypes[refType], "Invalid Reference Type")
		
		local last = Objects[refType]
		for i,v in ipairs(objects) do
			last = last[v]
			
			if not last then
				break
			end
		end
		
		local refData = last and last.__Data
		return refData and refData.Reference or nil
	end
end
