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

WFCatTrashTestSession.lua

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

ADOBE CONFIDENTIAL
------------------
Copyright 2019 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.

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

	-- RxLua
local Rx = require 'Rx'
local Observable = Rx.Observable

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

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

	-- WF.core.utils
local WFRxThrottledBatchedApplyOverlayToIds = require 'WFRxThrottledBatchedApplyOverlayToIds'
local KSIdGenerator = require 'KSIdGenerator'
local KSTableUtils = require 'KSTableUtils'

	-- WF.oz_client.managed_catalog
local WFCatBinaryUploader = require 'WFCatBinaryUploader'
local WFCatConflictResolver = require 'WFCatConflictResolver'
local WFCatErrorHandler = require 'WFCatErrorHandler'
local WFCatMetadataPuller = require 'WFCatMetadataPuller'
local WFCatMetadataPusher = require 'WFCatMetadataPusher'
local WFCatMockCatalog = require 'WFCatMockCatalog'
local WFCatSpecMock = require 'WFCatSpecMock'
local WFCatOzTestSession = require 'WFCatOzTestSession'


local logger = require 'WFLogger'( 'WFCatTrashTestSession' )

local doRequestResponseLogging = require 'WFConfiguration'.trashTest.enableRequestResponseLogging

if doRequestResponseLogging then
	logger:enable( 'logfile' )
end


local kOptIndexSpec
local kAlbumAssetQuery
if WFPlatformInfo.isDesktop then
	kAlbumAssetQuery = [[SELECT album_asset_v2.docId, album_asset_v2.assetId FROM CARRAY( ?, ?, 'char*' ) AS ai JOIN album_asset_v2 ON
							ai.value = album_asset_v2.assetId]]
else
	kOptIndexSpec = 'LrmCatalogIndexDefinitions.lua'
	kAlbumAssetQuery = [[SELECT album_asset.docId, album_asset.assetId FROM CARRAY( ?, ?, 'char*' ) AS ai JOIN album_asset ON
							ai.value = album_asset.assetId]]
end

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

local function bulkDelete( catalog, docIds  )

	-- very simple bulkDelete that does not delete album_assets automatically

	local overlay = {
		_deleted = true,
		_localOnly = { deletedLocally = true },
	}

	return WFRxThrottledBatchedApplyOverlayToIds( "bulkDeleteTest", catalog:docStore(), overlay, docIds, 100, 10 )

end

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

local function deleteDoc( catalog, docId )
	return bulkDelete( catalog, { docId } )
end

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

local continuousTaskDelays = {
	progressiveBackoff = false,
	noWorkDelay = 1,
	maxNoWorkDelay = 1,
	errorDelay = 1,
	maxDelay = 1,
}

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

local function albumAssetsForFilteredAssetsQueryFn( catalog, assetIds )

	-- This function is used to find album_assets related to assets that
	-- are blocked from upload because of an ozError.

	return catalog:indexStore():queryOnce {
		sql = kAlbumAssetQuery,
		assetIds,
		#assetIds,
	}

end

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

local function setupMockedCatalog( rxTest, catalogId, options )

	options = options or {}

	local userId = '87f526b44f9e41eca6cb5a550f84ceb6'

	local catalogSpec = WFCatSpecMock( catalogId, userId, rxTest, {} )
	local catalog = WFCatMockCatalog.createWFCatalogForTestWithSpec( rxTest, catalogSpec, options.catalogClassType, kOptIndexSpec )

	local conflictResolver = WFCatConflictResolver( catalog:docStore(), catalog:indexStore() )
	rxTest:addCloseTarget( conflictResolver )

	local capabilities = {
		[ 'WFCatBinaryUploader.atomicDevelopSettings' ] = options.atomicDevelopSettings,
	}

	local pusher = WFCatMetadataPusher( catalog, {
			delayBeforeSendingUpdates = .01,
			continuousTaskDelays = continuousTaskDelays,
			albumAssetsForFilteredAssetsQueryFn = albumAssetsForFilteredAssetsQueryFn,
			capabilities = capabilities,
		} )

	rxTest:addCloseTarget( pusher )

	local pullerOptions = {
		continuousTaskDelays = continuousTaskDelays,
		isCatalogPuller = true,
	}

	local puller = WFCatMetadataPuller( catalog, "Test Puller", pullerOptions )
	rxTest:addCloseTarget( puller )

	local uploader = WFCatBinaryUploader( catalog, nil, continuousTaskDelays, nil, {
			fallbackToOzUploadForOriginalsOnly = true,
			clearFromRecentlyUploadedSeconds = 1,
			timer = function( seconds )
				return Observable.timer( seconds, WFRxScheduler.sharedScheduler() )
			end,
			capabilities = capabilities,
		} )

	rxTest:finally( function()

		uploader:stopContinuousUploads()
		uploader:close()

		catalog:indexStore():close()

	end )

	return catalog, catalogSpec, pusher, puller, uploader, conflictResolver

end

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

local function setupTestSession( rxTest, options )

	local testSession, catalog, catalogSpec, pusher, puller, uploader, conflictResolver

	if options.mock then

		local mockedCatalogId = KSIdGenerator.uuidInLowercaseHex()
		catalog, catalogSpec, pusher, puller, uploader, conflictResolver = setupMockedCatalog( rxTest, mockedCatalogId, options )
		testSession = true

	else

		local ozTestOptions = {
			catalogSpecSpy = true,
			logger = doRequestResponseLogging and logger or nil,
		}
		ozTestOptions = KSTableUtils.merge( {}, ozTestOptions, options )

		testSession, catalog, catalogSpec, pusher, puller, uploader, conflictResolver =
			WFCatOzTestSession.setupOzTest( rxTest, ozTestOptions )
		assert( testSession )

	end

	local catSyncStatus = WFPlatformInfo.isDesktop and require 'WFCatSyncStatus' or require 'LrmCatSyncStatus'

	local errorHandler = WFCatErrorHandler( catalog,
		{
			deleteAssets = bulkDelete,
			deleteIndividualAlbum = deleteDoc,
			getSyncStatusOfAssetsOfAlbumAssets = catSyncStatus.getSyncStatusOfAssetsOfAlbumAssets,
			getSyncStatusOfAlbumsOfAlbumAssets = catSyncStatus.getSyncStatusOfAlbumsOfAlbumAssets,
			getSyncStatusOfParentCollectionOfAlbums = catSyncStatus.getSyncStatusOfParentCollectionOfAlbums,
		},
		{ debugMode = true } )

	rxTest:addCloseTarget( errorHandler )

	local pusherControl = {
		pauseReturningCounter = function()
			return pusher:pauseReturningCounter()
		end,
		resume = function()
			return pusher:resume()
		end,
	}

	return testSession, catalog, catalogSpec, pusher, puller, uploader, pusherControl, errorHandler, conflictResolver

end

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

return {
	setupTestSession = setupTestSession,
}
