local Rx = require 'Rx'

local Observable = Rx.Observable
local SchedulerArgument = Rx.internals.SchedulerArgument

local unpack = table.unpack or unpack

--------------------------------------------------------------------------------

return function(fn, ...)

    local values = { ... }
    local nValues = select('#', ...)

    if type(fn) ~= 'function' then
        error("Observable.pcall: first argument must be a function", 2)
    end

    local stripLastArg, scheduler = SchedulerArgument.fromVarArgs('Rx.Observable.pcall',
                                                                  'immediate', ...)
    if stripLastArg then
        nValues = nValues - 1
    end

    local function finishMakeObservable(success, ...)

        local function appendSchedulerToArgs(...)

            local args = { ... }
            local nArgs = select('#', ...)

            args[nArgs + 1] = scheduler

            return unpack(args, 1, nArgs + 1)

        end

        if success then

            local maybeObservable = (...)
            local nArgs = select('#', ...)

            if nArgs == 0 then
                return Observable.empty(scheduler)
            elseif Observable:isClassOf(maybeObservable) then
                return maybeObservable
            else
                return Observable.just(appendSchedulerToArgs(...))
            end

        else

            return Observable.throw(appendSchedulerToArgs(...))

        end

    end

    return finishMakeObservable(pcall(fn, unpack(values, 1, nValues)))

end
