local tokensKey = KEYS[1]

local interval = tonumber(ARGV[1])
local rate = tonumber(ARGV[2])
local capacity = tonumber(ARGV[3])
local timestamp = tonumber(ARGV[4])
local requested = tonumber(ARGV[5] or 1)

local fillTime = capacity / (rate / interval);
local ttl = math.floor(fillTime * 2)

local lastTokens = tonumber(redis.call("hget", tokensKey, "tokens"))
if lastTokens == nil then
  lastTokens = capacity
end

local lastRefreshed = tonumber(redis.call("hget", tokensKey, "timestamp"))
if lastRefreshed == nil then
  lastRefreshed = 0
end

local delta = math.max(0, (timestamp - lastRefreshed) / interval)
local filled = math.min(capacity, lastTokens + math.floor(delta * rate));
local allowed = filled >= requested
local newTokens = filled
if allowed then
  newTokens = filled - requested
end

redis.call("hset", tokensKey, "tokens", newTokens, "timestamp", timestamp)
redis.call("expire", tokensKey, ttl)

return { allowed, newTokens }
