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

ADOBE CONFIDENTIAL
___________________

Copyright 2020 Adobe

All Rights Reserved.

NOTICE: All information contained herein is, and remains
the property of Adobe and its suppliers, if any. The intellectual
and technical concepts contained herein are proprietary to Adobe
and its suppliers and are protected by all applicable intellectual
property laws, including trade secret and copyright laws.
Dissemination of this information or reproduction of this material
is strictly forbidden unless prior written permission is obtained
from Adobe.
------------------------------------------------------------------------------]]

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

if not WFPlatformInfo.isMobile() then
       return {}
end

	-- RxLua
local Rx = require 'Rx'

	-- WF.core.utils
local WFArguments = require 'WFArguments'
local KSPathUtils = require 'KSPathUtils'

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

	-- WF.oz_client.managed_catalog.sync
local WFOzUserTestSession = require 'WFOzUserTestSession'
local WFCatUser = require 'WFCatUser'
local WFCatalog = require 'WFCatalog'

	-- lrmobile
local LrmSyncClient = require 'LrmSyncClient'

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

local check = assert( WFArguments.check )

--==============================================================================

-- @mark LrmSyncClientTest namespace

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

local LrmSyncClientTest = {}

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

function LrmSyncClientTest.rxTestCallAllSyncClientBaseMethods_testNightly( rxTest )

	rxTest:setTimeLimit( 30 )
	rxTest:makeVerbose()

	local userTestSession = WFOzUserTestSession( rxTest, {
				suppressStoreTokens = true,
				v2 = true
			} )

	local user
	local catSpec
	local catalog

	local userInfoCachePath = KSPathUtils.child( KSPathUtils.getStandardFilePath 'temp', 'userCache' )
	local docStoreRootPath = KSPathUtils.getStandardFilePath 'temp'

	rxTest:expectSingleValue( userTestSession:getCleanOzAccount()

		:flatMapLatest( function( userId )

			check( 'uuid' )

			user = WFCatUser( userTestSession:ozServerBaseUrl(), userId, userInfoCachePath )

			rxTest:finally( function()

				local userDocStore = user:userInfoCache()

				userDocStore:haltAndDelete()

			end )

			local accessToken, refreshToken = userTestSession:accessAndRefreshTokens()

			return user:storeTokens( accessToken, refreshToken )
				:concat( Rx.Observable.just( true ) )
				:flatMapLatest( function()

					return user:createCatalog( 'lightroom' )

				end )

		end )

		:map( function( catalogSpec )

			check( 'WFCatSpec' )

			catSpec = catalogSpec

			catalog = WFCatalog( catalogSpec, docStoreRootPath, { } )

			rxTest:finally( function()

				catalog:docStore():haltAndDelete()
				catalog:indexStore():haltAndDelete()

			end )

			return true

		end ), true )

	-- The following code verifies that all of the methods within WFCatSyncClientBase
	-- are exposed as methods on the client-facing LrmSyncClient object. The code
	-- doesn't verify the methods work as expected, just that they're exposed.

	-- Note that there are different testing syntaxes at play
	-- here. The "subscription" pattern is used to check that
	-- methods are routed to their proper handler via __index -
	-- those methods _also_ return empty observables, so the
	-- `waitFor` pattern will not work. `waitFor` is prefered, but
	-- as it stands the conversion away from empty observables has
	-- not happened yet

	local syncClient = LrmSyncClient( catalog )
	local subscription

	-- Start sync
	rxTest:waitFor( syncClient:startSync() )

	-- Stop sync from within WF
	rxTest:waitFor( syncClient:stopSync_INTERNAL() )

	rxTest:expectSingleValue( syncClient:_DEBUG_getClientSyncAction(), 'standard' )

	-- Resuming should not cause any state changes around sync action
	rxTest:waitFor( syncClient:resume() )

	rxTest:expectSingleValue( syncClient:_DEBUG_getClientSyncAction(), 'standard' )

	rxTest:waitFor( syncClient:stopSync() )

	-- Internal WF sync pauses should not interfere with clientDirectedAction

	rxTest:waitFor( syncClient:startSync() )

	-- As the sync started from the client, clientSyncAction should be set
	rxTest:expectSingleValue( syncClient:_DEBUG_getClientSyncAction(), 'standard' )
	-- WF triggers a pause
	rxTest:waitFor( syncClient:lockSync( ) )
	rxTest:waitFor( syncClient:stopSync_INTERNAL() )

	-- client sync action is uneffected
	rxTest:expectSingleValue( syncClient:_DEBUG_getClientSyncAction(), 'standard' )

	-- WF resumes

	rxTest:waitFor( syncClient:resume() )
	rxTest:waitFor( syncClient:unlockSync( ) )

	-- client sync action is uneffected
	rxTest:expectSingleValue( syncClient:_DEBUG_getClientSyncAction(), 'standard' )

	-- client pauses sync
	rxTest:waitFor( syncClient:stopSync() )

	-- client sync action is stopped
	rxTest:expectSingleValue( syncClient:_DEBUG_getClientSyncAction(), 'stopped' )


	-- WF attempts to restart sync, but is stopped as the client specified a stop sync

	rxTest:expectSingleValue( syncClient:resume(), false )

	-- client sync action is stopped
	rxTest:expectSingleValue( syncClient:_DEBUG_getClientSyncAction(), 'stopped' )

	-- client restarts sync, their request has priority
	rxTest:expectSingleValue( syncClient:startSync(), true )

	-- client sync action is started
	rxTest:expectSingleValue( syncClient:_DEBUG_getClientSyncAction(), 'standard' )

	rxTest:waitFor( syncClient:startSyncInResidualMode() )

	subscription = syncClient:stopSyncInResidualMode():subscribe()
	subscription:dispose()

	rxTest:expectSingleValue( syncClient:_DEBUG_getClientSyncAction(), 'residual' )

	rxTest:waitFor( syncClient:startSpaceMetadataSyncInFreemiumMode() )

	rxTest:waitFor( syncClient:stopSpaceMetadataSyncInFreemiumMode() )

	subscription = syncClient:spaceFeedsMaintenanceNotificationStream():subscribe()
	subscription:dispose()

	rxTest:waitFor( syncClient:pausePusherReturningCounter() )

	rxTest:waitFor( syncClient:resumePusher() )

	rxTest:waitFor( syncClient:_DEBUG_startMetadataPusher() )

	rxTest:waitFor( syncClient:_DEBUG_stopMetadataPusher() )

	rxTest:waitFor( syncClient:setUserIsOverQuota( true ) )

	rxTest:waitFor( syncClient:setUserIsExpired( true ) )

	subscription = syncClient:isUploadingMetadata():subscribe()
	subscription:dispose()

	subscription = syncClient:isDownloadingMetadata():subscribe()
	subscription:dispose()

	subscription = syncClient:getLatestDownloadedAssetIdsStream():subscribe()
	subscription:dispose()

	subscription = syncClient:isOzCatalogDeleted():subscribe()
	subscription:dispose()

	subscription = syncClient:getRequiredUpdateStream():subscribe()
	subscription:dispose()

	subscription = syncClient:getSQLiteFatalErrorCodeStream():subscribe()
	subscription:dispose()

	subscription = syncClient:checkOzForUpdates():subscribe()
	subscription:dispose()

	subscription = syncClient:setReadNotification():subscribe()
	subscription:dispose()

	subscription = syncClient:setVisitedNotification():subscribe()
	subscription:dispose()

	subscription = syncClient:notificationUnreadCount():subscribe()
	subscription:dispose()

	subscription = syncClient:notificationList():subscribe()
	subscription:dispose()

	subscription = syncClient:notificationKillSwitch():subscribe()
	subscription:dispose()

	subscription = syncClient:haltAndDeleteNotificationDb():subscribe()
	subscription:dispose()

	subscription = syncClient:_DEBUG_simulateCorruptionNotificationDb():subscribe()
	subscription:dispose()

	-- Verify custom methods in LrmSyncClientImp
	----------------------------------------------------------------------------

	subscription = syncClient:isPushingMetadata():subscribe()
	subscription:dispose()

	subscription = syncClient:isPullingMetadata():subscribe()
	subscription:dispose()

	subscription = syncClient:getDeleteFeedCallback():subscribe()
	subscription:dispose()

	rxTest:waitFor( syncClient:startSyncWithoutUploader() )

	rxTest:expectSingleValue( syncClient:_DEBUG_getClientSyncAction(), 'standardNoUploader' )

	rxTest:waitFor( syncClient:startAccountsSync() )

	rxTest:waitFor( syncClient:stopAccountsSync() )

	rxTest:expectSingleValue( syncClient:_DEBUG_getClientSyncAction(), 'accounts' )

	rxTest:waitFor( syncClient:startSpaceSyncWithoutOzCatalog() )

	subscription = syncClient:getDetailedUploadProgress():subscribe()
	subscription:dispose()

	subscription = syncClient:getOzMaintenanceNotificationStream():subscribe()
	subscription:dispose()

	-- Verify return values of debug methods:
	----------------------------------------------------------------------------

	rxTest:expectSingleValue( syncClient:_DEBUG_SyncClientReturnsFoo(), 'foo' )

	rxTest:expectSingleValue( syncClient:_DEBUG_SyncClientBaseReturnsTrue(), true )

	-- Verify non existent methods cause an error:
	----------------------------------------------------------------------------

	rxTest:expectOnlyError( syncClient:foo(), ':ignore:' )

	syncClient:close()

end

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

return WFRxTestCase.wrapSuite( 'LrmSyncClientTest', LrmSyncClientTest )
