local Rx = require 'Rx'

local Observable = Rx.Observable

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

local function flatMap(self, selectorFn)

    return self:map(function(...)

        local observable = selectorFn(...)

        if not Observable:isClassOf(observable) then
            error("Rx.Observable:selectMany: must return observable from selector function", 3)
        end

        return observable

    end):flatMergeAll()

end

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

return function(self, selector, resultSelector, thisArg)

    if type(selector) == 'function' then

        if type(resultSelector) == 'function' then

            if thisArg then
                error("Rx.Observable:selectMany: thisArg not supported", 2)
            end

            return flatMap(self, function(x)

                local observable = selector(x)

                if not Observable:isClassOf(observable) then
                    error("Rx.Observable:selectMany: must return observable from selector function", 3)
                end

                return observable:map(function(y)
                    return resultSelector(x, y)
                end)

            end, self)

        else

            thisArg = resultSelector
            if thisArg then
                error("Rx.Observable:selectMany: thisArg not supported", 2)
            end

            return flatMap(self, selector)

        end

    else
        return flatMap(self, function() return selector end)
    end

end
