--!native
--!nonstrict
--!optimize 2
-- Compiled with roblox-ts v2.3.0
local TS = _G[script]
local t = TS.import(script, TS.getModule(script, "@rbxts", "t").lib.ts).t
local isValidCapacity = t.intersection(t.integer, t.numberMin(0))
--[[
	*
	 * A LRUCache (least recently used cache) is a type of cache that is
	 * used to store a limited number of items. When an item is added to the
	 * cache, if the item already exists in the cache, it is moved to the
	 * end of the list. If the item does not already exist in the cache, it
	 * is added to the end of the list.
	 
]]
local LRUCache
do
	LRUCache = setmetatable({}, {
		__tostring = function()
			return "LRUCache"
		end,
	})
	LRUCache.__index = LRUCache
	function LRUCache.new(...)
		local self = setmetatable({}, LRUCache)
		return self:constructor(...) or self
	end
	function LRUCache:constructor(capacity)
		self.size = 0
		self.head = {}
		self.nodesMap = {}
		self.tail = {}
		local _arg0 = isValidCapacity(capacity)
		assert(_arg0, "Capacity must be a number greater than 0")
		self.capacity = capacity
	end
	function LRUCache:get(key)
		local _nodesMap = self.nodesMap
		local _key = key
		local node = _nodesMap[_key]
		if not node then
			return nil
		end
		self:evict(node)
		self:append(node)
		return node.value
	end
	function LRUCache:set(key, value)
		local _nodesMap = self.nodesMap
		local _key = key
		local node = _nodesMap[_key]
		if node then
			node.value = value
			self:evict(node)
			self:append(node)
		else
			self:append({
				key = key,
				value = value,
			})
		end
	end
	function LRUCache:append(node)
		local _nodesMap = self.nodesMap
		local _key = node.key
		local _node = node
		_nodesMap[_key] = _node
		local _binding = self
		local head = _binding.head
		local tail = _binding.tail
		if head.next then
			local tailPrevious = tail.previous
			tailPrevious.next = node
			node.previous = tailPrevious
			node.next = tail
			tail.previous = node
		else
			head.next = node
			tail.previous = node
			node.previous = head
			node.next = tail
		end
		local size = self.size + 1
		self.size = size
		if size > self.capacity then
			self:evict(head.next)
		end
	end
	function LRUCache:evict(node)
		local _nodesMap = self.nodesMap
		local _key = node.key
		_nodesMap[_key] = nil
		self.size -= 1
		local previousNode = node.previous
		local nextNode = node.next
		local _binding = self
		local head = _binding.head
		local tail = _binding.tail
		if previousNode == head and nextNode == tail then
			head.next = nil
			tail.previous = nil
			self.size = 0
			return nil
		end
		if previousNode == head then
			nextNode.previous = head
			head.next = nextNode
			return nil
		end
		if nextNode == tail then
			previousNode.next = tail
			tail.previous = previousNode
			return nil
		end
		previousNode.next = nextNode
		nextNode.previous = previousNode
	end
	LRUCache.instanceof = function(value)
		local _value = value
		local _condition = type(_value) == "table"
		if _condition then
			_condition = getmetatable(value) == LRUCache
		end
		return _condition
	end
end
return {
	LRUCache = LRUCache,
}
