local Rx = require 'Rx'

local AbstractObserver = Rx.AbstractObserver
local CompositeDisposable = Rx.CompositeDisposable
local ObservableBase = Rx.ObservableBase

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

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

    AbstractObserver,
        -- superclass

    _observer = false,
        -- (Observer)

    _skipWhileObservable = false,
        -- (SkipWhileObservable)

    _running = false,
        -- (boolean)

    __init = function(self, observer, skipWhileObservable)

        self._observer = observer
        self._skipWhileObservable = skipWhileObservable
        self._running = false

    end,

    next = function(self, ...)

        if not self._running then

            local success, resultOrError = pcall(self._skipWhileObservable._predicateFn, ...)
            if not success then
                return self._observer:onError(resultOrError)
            end

            self._running = not resultOrError

        end

        if self._running then
            self._observer:onNext(...)
        end

    end,

    error = function(self, ...)
        self._observer:onError(...)
    end,

    completed = function(self)
        self._observer:onCompleted()
    end,

}

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

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

    ObservableBase,
        -- superclass

    _source = false,
        -- (Observable)

    _predicateFn = false,
        -- (function)

    __init = function(self, source, predicateFn)

        self._source = source
        self._predicateFn = predicateFn

    end,

    subscribeCore = function(self, observer)

        local skipWhileObserver = SkipWhileObserver(observer, self)

        return CompositeDisposable(self._source:subscribe(skipWhileObserver),
            skipWhileObserver)

    end,

}

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

return function(self, predicateFn, thisArg)

    if type(predicateFn) ~= 'function' then
        error("Rx.Observable:skipWhile: predicateFn must be a function", 2)
    end

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

    return SkipWhileObservable(self, predicateFn)

end
