local Rx = require 'Rx'

local ReactiveTest = Rx.testing.ReactiveTest
local Recorded = Rx.testing.Recorded

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

local testSchedulerPrototype = { Rx.VirtualTimeScheduler }

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

function testSchedulerPrototype:__init()

    return 0

end

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

function testSchedulerPrototype:scheduleAbsolute(state, dueTime, action)

    if action == nil then
        action = dueTime
        dueTime = state
        state = nil
    end

    if dueTime <= self._clock then
        dueTime = self._clock + 1
    end

    return self:Rx_VirtualTimeScheduler_scheduleAbsolute(state, dueTime, action)

end

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

function testSchedulerPrototype:startScheduler(createFn, settings)

    settings = settings or {}

    if settings.created == nil then
        settings.created = ReactiveTest.created
    end

    if settings.subscribed == nil then
        settings.subscribed = ReactiveTest.subscribed
    end

    if settings.disposed == nil then
        settings.disposed = ReactiveTest.disposed
    end

    local observer = self:createObserver()
    local source
    local subscription

    self:scheduleAbsolute(settings.created, function()
        source = createFn()
    end)

    self:scheduleAbsolute(settings.subscribed, function()
        subscription = source:subscribe(observer)
    end)

    self:scheduleAbsolute(settings.disposed, function()
        subscription:dispose()
    end)

    self:start()

    return observer

end

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

local function argsOrArray(...)

    local n = select('#', ...)
    local first = (...)

    if n == 1 and not Recorded:isClassOf(first) then
        return first
    else
        return { ... }
    end

end

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

function testSchedulerPrototype:createHotObservable(...)

    local messages = argsOrArray(...)
    return Rx.testing.HotObservable(self, messages)

end

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

function testSchedulerPrototype:createColdObservable(...)

    local messages = argsOrArray(...)
    return Rx.testing.ColdObservable(self, messages)

end

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

function testSchedulerPrototype:createObserver()

    return Rx.testing.MockObserver(self)

end

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

return Rx.Class('Rx.testing.TestScheduler', testSchedulerPrototype)
