local redis = require "resty.redis"
local error = require "sm.utils.error"
local cjson = require "cjson"

local M = {}

-- Connect to Redis
function M.connect(config)
    -- Sanity checks
    if type(config["host"]) ~= "string" then
        return nil, error("Host must be a string")
    end

    if type(config["port"]) ~= "number" then
        return nil, error("Port must be a number")
    end

    if type(config["timeout"]) ~= "number" then
        return nil, error("Timeout must be a number")
    end

    local red = redis:new()

    red:set_timeout(config["timeout"])

    local ok, err = red:connect(config["host"], config["port"])
    if err then
        return nil, error(err)
    end
    local res, err = red:auth(config["password"])
    if not res then
        return nil, error(err)
    end

    ngx.ctx.redis = red

    return true
end

-- Close connection
function M.close()
    -- ngx.log(ngx.INFO, "closing redis connection")
    if ngx.ctx.redis then
        local ok, err = ngx.ctx.redis:set_keepalive(10000, 256)
        if not ok then
            return nil, error(err)
        end
        ngx.ctx.redis = nil
    end
end

-- Get value
function M.get(key)
    local res, err = ngx.ctx.redis:get(key)
    if not res or res == ngx.null then
        return nil, error(err)
    end

    return res
end

-- Get all hash keys
function M.hgetall(key)
    local res, err = ngx.ctx.redis:hgetall(key)
    if err then
        ngx.log(ngx.ERR, "error getting hash all: " .. cjson.encode(err))
        return nil, error(err)
    elseif not res or next(res) == nil then
        return nil
    end

    -- Reconstruct into table
    local final = {}
    for v = 1, #res, 2 do
        final[res[v]] = res[v + 1]
    end

    return final
end

return M
