local Rx = require 'Rx'

local Disposable = Rx.Disposable

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

local compositeDisposablePrototype = {

    Disposable,
        -- superclass

    _disposables = false,
        -- (array of Disposable) items to be disposed

}

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

local function cloneArray(array)

    local result = {}
    for i = 1, #array do
        result[i] = array[i]
    end

    return result

end

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

function compositeDisposablePrototype:__init(...)

    local disposables = { ... }

    for i = 1, #disposables do
        if not Disposable:isClassOf(disposables[i]) then
            error(string.format(
                "Rx.CompositeDisposable: object #%d is not a Disposable", i), 3)
        end
    end

    self._disposables = disposables

    return function()

        local currentDisposables = cloneArray(self._disposables)
        self._disposables = {}

        for i = 1, #currentDisposables do
            currentDisposables[i]:dispose()
        end

    end

end

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

function compositeDisposablePrototype:add(item)

    if not Disposable:isClassOf(item) then

        error(string.format("Rx.CompositeDisposable: item (%s) is not a Disposable",
            tostring(item)), 2)

    end

    if self:isDisposed() then
        item:dispose()
    else
        local disposables = self._disposables
        disposables[#disposables + 1] = item
    end

end

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

function compositeDisposablePrototype:remove(item)

    local disposables = self._disposables

    for i = 1, #disposables do
        local maybeItem = disposables[i]
        if maybeItem == item then
            table.remove(disposables, i)
            item:dispose()
            return true
        end
    end

    return false

end

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

function compositeDisposablePrototype:length()

    return #self._disposables

end

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

function compositeDisposablePrototype:toArray()

    return cloneArray(self._disposables)

end

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

return Rx.Class('Rx.CompositeDisposable', compositeDisposablePrototype)
