local Rx = require 'Rx'

local Observable = Rx.Observable

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

local function concatMap(self, selectorFn)

    return self:map(function(x)

        local observable = selectorFn(x)

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

        return observable

    end):concatAll()

end

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

return function(self, selector, resultSelector, thisArg)

    if type(selector) == 'function' then

        if type(resultSelector) == 'function' then

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

            return concatMap(self, function(x)

                local observable = selector(x)

                if not Observable:isClassOf(observable) then
                    error("Rx.Observable:concatMap: 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:concatMap: thisArg not supported", 2)
            end

            return concatMap(self, selector)

        end

    else

        return concatMap(self, function() return selector end)

    end

end
