--[[
	https://github.com/moteus/lua-try
	https://github.com/djfdyuruiry/lua-try-catch-finally
]]
local functionType = "function"
local xpcall = xpcall
local type = type
local error = error
local debug = debug

---
-- @param tryBlock  any The block of code to execute as the try block.
--
-- @return table that can be used to chain try/catch/finally blocks. (Call .catch or .finally of the return value)
--
return function(tryBlock)
    local status, err = true, nil

    if type(tryBlock) == functionType then
        status, err = xpcall(tryBlock, debug.traceback)
    end

    local finally = function(finallyBlock, catchBlockDeclared)
        if type(finallyBlock) == functionType then
            finallyBlock()
        end

        if not catchBlockDeclared and not status then
            error(err)
        end
    end

    local catch = function(catchBlock)
        local catchBlockDeclared = type(catchBlock) == functionType

        if not status and catchBlockDeclared then
            local ex = err or "unknown error occurred"
            catchBlock(ex)
        end

        return {
            finally = function(finallyBlock)
                finally(finallyBlock, catchBlockDeclared)
            end,
        }
    end

    return {
        catch = catch,
        finally = function(finallyBlock)
            finally(finallyBlock, false)
        end,
    }
end

-- local try = require "try"

-- local object

-- try(function ()
--     object = Object()
--     object:doRiskyStuff()
-- end)
-- .catch(function (ex)
--     print(ex)
-- end)
-- .finally(function ()
--     if object then
--         object:dispose()
--     end
-- end)
