--[[----------------------------------------------------------------------------

ADOBE CONFIDENTIAL
------------------
Copyright 2016 Adobe Systems Incorporated
All Rights Reserved.

NOTICE: All information contained herein is, and remain the property of
Adobe Systems Incorporated and its suppliers, if any. The intellectual and
technical concepts contained herein are proprietary to Adobe Systems
Incorporated and its suppliers and may be covered by U.S. and Foreign
Patents, patents in process, and are protected by trade secret or copyright
law.  Dissemination of this information or reproduction of this material is
strictly forbidden unless prior written permission is obtained from
Adobe Systems Incorporated.

----------------------------------------------------------------------------]]--

	-- RxLua
local Rx = require 'Rx'

	-- WF.core.self_test
local WFRxTestCase = require 'WFRxTestCase'

	-- WF.core.os
local KSDate = require 'KSDate'

 	-- WF.core.rxlua
local WFRxDifferenceFilterWithWindowObservable = require 'WFRxDifferenceFilterWithWindowObservable'
local WFRxScheduler = require 'WFRxScheduler'

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

local filterDiffWithWindow = WFRxDifferenceFilterWithWindowObservable

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

local WFRxDifferenceFilterWithWindowObservableTest = {}

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

local function emitValues( ...  )

	local values = { ... }
	local nValues = select( '#', ... )
		
	return Rx.Observable.create( function( observer )
	
		for i = 1, nValues do
		
			local value = values[ i ]
			
			observer:onNext( value )
			
		end
		
	end )
	
end

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

function WFRxDifferenceFilterWithWindowObservableTest.rxTestImmediateDelivery( rxTest )

	local o = Rx.Observable.just( 100 )
		:call( filterDiffWithWindow, 100, 5, WFRxScheduler.sharedScheduler() )
		
	local obs = rxTest:observe( o )
	
	obs:expectDataWithinTime( 1, 100 )
	
end

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

function WFRxDifferenceFilterWithWindowObservableTest.rxTestDelayedDelivery( rxTest )

	rxTest:setTimeLimit( 10 )
	
	local start = KSDate.timeNowForAnimation()
	local delta
	
	local o = emitValues( 50 )
		:call( filterDiffWithWindow, 100, 2, WFRxScheduler.sharedScheduler() )
		:tap( function()
		
			delta = KSDate.timeNowForAnimation() - start
			
		end )
		
	local obs = rxTest:observe( o )
	
	obs:expectDataWithinTime( 5, 50 )
	
	rxTest:expectEqual( true, delta >= 2 )
	
end

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

function WFRxDifferenceFilterWithWindowObservableTest.rxTestLatestValue( rxTest )

	rxTest:setTimeLimit( 10 )
	
	local o = emitValues( 1, 4, 8, 12 )
		:call( filterDiffWithWindow, 20, 2, WFRxScheduler.sharedScheduler() )
		
	
	local obs = rxTest:observe( o )
	
	obs:expectDataWithinTime( 3, 12 )
	
end

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

function WFRxDifferenceFilterWithWindowObservableTest.rxTestDeliverValueBeforeTimeout( rxTest )

	rxTest:setTimeLimit( 10 )
	
	local subject = Rx.Subject()
	
	local o = subject
		:call( filterDiffWithWindow, 5, 7, WFRxScheduler.sharedScheduler() )
	
	local obs = rxTest:observe( o )
	
	subject:onNext( 2 )
	
	rxTest:sleep( 1 )
	
	subject:onNext( 8 )
	
	obs:expectDataWithinTime( 3, 8 )
	
end

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

function WFRxDifferenceFilterWithWindowObservableTest.rxTestImmediateCompleted( rxTest )

	local o = Rx.Observable.just( 42 )
		:call( filterDiffWithWindow, 5, 10, WFRxScheduler.sharedScheduler() )
		
	local obs = rxTest:observe( o )
	
	obs:expectCompletedWithinTime( 1 )
	
end

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

function WFRxDifferenceFilterWithWindowObservableTest.rxTestImmediateError( rxTest )

	local o = Rx.Observable.throw( 'bad' )
		:call( filterDiffWithWindow, 5, 10, WFRxScheduler.sharedScheduler() )
		
	local obs = rxTest:observe( o )
	
	obs:expectErrorWithinTime( 1, 'bad' )
	
end

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

function WFRxDifferenceFilterWithWindowObservableTest.rxTestBadValues( rxTest )

	local scheduler = WFRxScheduler.sharedScheduler()

	rxTest:expectError( function()
	
		local o = Rx.Observable.just( 'foo' )
			:call( filterDiffWithWindow, 5, 10, scheduler )
			
		rxTest:expectSingleValue( o, 'foo' )
			
	end )
	
	rxTest:expectError( function()
	
		local o = Rx.Observable.just( false )
			:call( filterDiffWithWindow, 5, 10, scheduler )
			
		rxTest:expectSingleValue( o, 'foo' )
			
	end )
	
	rxTest:expectError( function()
	
		local o = Rx.Observable.just( {} )
			:call( filterDiffWithWindow, 5, 10, scheduler )
			
		rxTest:expectSingleValue( o, 'foo' )
			
	end )
	
	rxTest:expectError( function()
	
		local o = Rx.Observable.just( 10, false )
			:call( filterDiffWithWindow, 5, 10, scheduler )
			
		rxTest:expectSingleValue( o, 'foo' )
			
	end )
	
end

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

function WFRxDifferenceFilterWithWindowObservableTest.rxTestBadArguments( rxTest )

	local scheduler = WFRxScheduler.sharedScheduler()

	-- test invalid arguments for difference
	
	rxTest:expectError( function()
		
		Rx.Observable.just( 42 )
			:call( filterDiffWithWindow, false, 10, scheduler )
			
	end )
	
	rxTest:expectError( function()
		
		Rx.Observable.just( 42 )
			:call( filterDiffWithWindow, 'foo', 10, scheduler )
			
	end )
	
	rxTest:expectError( function()
		
		Rx.Observable.just( 42 )
			:call( filterDiffWithWindow, {}, 10, scheduler )
			
	end )
	
	rxTest:expectError( function()
		
		Rx.Observable.just( 42 )
			:call( filterDiffWithWindow, -1, 10, scheduler )
			
	end )
	
	rxTest:expectError( function()
		
		Rx.Observable.just( 42 )
			:call( filterDiffWithWindow, 0, 10, scheduler )
			
	end )
	
	-- test invalid arguments for window
	
	rxTest:expectError( function()
		
		Rx.Observable.just( 42 )
			:call( filterDiffWithWindow, 42, false, scheduler )
			
	end )
	
	rxTest:expectError( function()
		
		Rx.Observable.just( 42 )
			:call( filterDiffWithWindow, 42, 'foo', scheduler )
			
	end )
	
	rxTest:expectError( function()
		
		Rx.Observable.just( 42 )
			:call( filterDiffWithWindow, 42, {}, scheduler )
			
	end )
	
	rxTest:expectError( function()
		
		Rx.Observable.just( 42 )
			:call( filterDiffWithWindow, 42, -1, scheduler )
			
	end )
	
	rxTest:expectError( function()
		
		Rx.Observable.just( 42 )
			:call( filterDiffWithWindow, 42, 0, scheduler )
			
	end )
	
	-- test invalid argument for scheduler
	
	rxTest:expectError( function()
		
		Rx.Observable.just( 42 )
			:call( filterDiffWithWindow, 42, 3 )
			
	end )
	
	rxTest:expectError( function()
		
		Rx.Observable.just( 42 )
			:call( filterDiffWithWindow, 42, 3, nil )
			
	end )
	
	rxTest:expectError( function()
		
		Rx.Observable.just( 42 )
			:call( filterDiffWithWindow, 42, 3, {} )
			
	end )
	
end

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

return WFRxTestCase.wrapSuite( 'WFRxDifferenceFilterWithWindowObservableTest', WFRxDifferenceFilterWithWindowObservableTest )
