local Rx = require 'Rx'

local CompositeDisposable = Rx.CompositeDisposable
local Disposable = Rx.Disposable
local Observable = Rx.Observable
local ObservableBase = Rx.ObservableBase

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

local UsingObservable = Rx.Class 'Rx.internals.UsingObservable' {

    ObservableBase,
        -- superclass

    _resourceFactoryFn = false,
        -- (function)

    _observableFactoryFn = false,
        -- (function)

    __init = function(self, resourceFactoryFn, observableFactoryFn)
        self._resourceFactoryFn = resourceFactoryFn
        self._observableFactoryFn = observableFactoryFn
    end,

    subscribeCore = function(self, observer)

        local disposable
        local source

        local success, err = pcall(function()

            local resource = self._resourceFactoryFn()
            disposable = resource or Disposable.empty()
            source = self._observableFactoryFn(resource)

        end)

        if not success then

            return CompositeDisposable(Observable.throw(err):subscribe(observer),
                disposable)

        else

            return CompositeDisposable(source:subscribe(observer), disposable)

        end

    end,

}

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

return function(resourceFactory, observableFactory)
    return UsingObservable(resourceFactory, observableFactory)
end
