local Rx = require 'Rx'

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

local function noop() end

-- TODO [pkamin 2014-12-02]: implement real defaultOnError function.

local function defaultOnError(e) error(e) end

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

local observerProtoType = { class = {} }

local AnonymousObserver_lazy
local CheckedObserver_lazy
local ObserveOnObserver_lazy
local Notification_lazy

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

function observerProtoType.class:create(onNext, onError, onComplete)

    if not onNext then
        onNext = noop
    end

    if not onError then
        onError = defaultOnError
    end

    if not onComplete then
        onComplete = noop
    end

    AnonymousObserver_lazy = AnonymousObserver_lazy or Rx.AnonymousObserver

    return AnonymousObserver_lazy(onNext, onError, onComplete)

end

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

function observerProtoType:toNotifier()

    local observer = self

    return function(n)
        return n:accept(observer)
    end

end

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

function observerProtoType.class:fromNotifier(handler)

    AnonymousObserver_lazy = AnonymousObserver_lazy or Rx.AnonymousObserver
    Notification_lazy = Notification_lazy or Rx.Notification

    return AnonymousObserver_lazy(
        function(...)
            return handler(Notification_lazy.createOnNext(...))
        end,
        function(...)
            return handler(Notification_lazy.createOnError(...))
        end,
        function()
            return handler(Notification_lazy.createOnCompleted())
        end
    )

end

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

function observerProtoType:asObserver()

    local onNext = function(...) return self:onNext(...) end
    local onError = function(...) return self:onError(...) end
    local onCompleted = function(...) return self:onCompleted(...) end

    AnonymousObserver_lazy = AnonymousObserver_lazy or Rx.AnonymousObserver

    return AnonymousObserver_lazy(onNext, onError, onCompleted)

end

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

function observerProtoType:checked()

    CheckedObserver_lazy = CheckedObserver_lazy or Rx.CheckedObserver

    return CheckedObserver_lazy(self)

end

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

function observerProtoType:notifyOn(scheduler)

    ObserveOnObserver_lazy = ObserveOnObserver_lazy or Rx.ObserveOnObserver

    -- ObserveOnObserver validates for a correct Scheduler

    return ObserveOnObserver_lazy(scheduler, self)

end

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

return Rx.Class('Rx.Observer', observerProtoType)
