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

WFCatPurgeHelper.lua

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

ADOBE CONFIDENTIAL
------------------
Copyright 2021 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.utils
local KSPathUtils = require 'KSPathUtils'
local KSTableUtils = require 'KSTableUtils'
local WFArguments = require 'WFArguments'
local WFFileUtils = require 'WFFileUtils'
local WFLogger = require 'WFLogger'
local WFOzDocUtils = require 'WFOzDocUtils'
local WFPlatformInfo = require 'WFPlatformInfo'
local WFRxThrottledBatchedBulkApplyOverlay = require 'WFRxThrottledBatchedBulkApplyOverlay'
local WFRxThrottledBatchedBulkDocValue = require 'WFRxThrottledBatchedBulkDocValue'
local WFTableMerge = require 'WFTableMerge'

	-- WF.oz_client.managed_catalog
local WFCatAssetAux = require 'WFCatAssetAux'
local WFCatDelete = require 'WFCatDelete'
local WFCatVolumeAgentQueryHelper = require 'WFCatVolumeAgentQueryHelper'

local LrmOzPurgeAgentUtils

if WFPlatformInfo.isMobile() then
	LrmOzPurgeAgentUtils = require 'LrmOzPurgeAgentUtils'
end

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

local logger = WFLogger "WFCatPurgeHelper"

local check = assert( WFArguments.check )

local KSTableUtils_derefOpt = assert( KSTableUtils.derefOpt )
local KSTableUtils_appendArray = assert( KSTableUtils.appendArray )

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

local WFCatPurgeHelper = {}

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

local function maybeDeleteAuxParentFolder( absolutePath )

	-- Delete Aux subfolders if they are empty.

	local parentPath = KSPathUtils.parent( absolutePath )
	local grandParentPath = parentPath and KSPathUtils.parent( parentPath )

	if grandParentPath and KSPathUtils.leafName( grandParentPath ) == 'auxiliary' then

		if WFFileUtils.exists( parentPath ) then

			local onlyDeleteIfEmpty = true
			WFFileUtils.deleteDirectory( parentPath, onlyDeleteIfEmpty )

		end

	end

end

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

 WFCatPurgeHelper.DEBUG_optOutDeletionBacklog = false

local getFilePathsToDeleteAndOverlay
local deleteFilePaths

if WFPlatformInfo.isDesktop then

	getFilePathsToDeleteAndOverlay = function( wfCatalog, baseBinariesPath,
		docValues, purgeList, binaryTypesToPurge, needToUpdateDocValue,
		keepRedactedBinaries, binaryTypesToDerefence,
		deletingForSpaceOperation )

		binaryTypesToPurge = binaryTypesToPurge or {}
		binaryTypesToDerefence = binaryTypesToDerefence or {}

		local filePathsToDelete = {}
		local overlays = {}

		for i, docValue in pairs( docValues ) do
		
			local shouldRemoveFiles = false
		
			if deletingForSpaceOperation then
			
				-- The following checks are only necessary if the purge operation is being triggered
				-- via the shared space workflows. Purge operations triggered via the purge agent
				-- perform similar checks prior to calling WFCatPurgeHelper.
			
				if docValue.type == 'version' then
			
					-- WF-1394: Prevent removing unsynced Version binary annotations. This allows us to resync these
					-- versions if the user is promoted to editor once again. PixelProviderFileCachePurgeWorker
					-- will also not purge the version binaries for this case.
					
					local isVersionOnOz = KSTableUtils_derefOpt( docValue, '_serverProvidedMetadata', 'links' ) ~= nil
				
					shouldRemoveFiles = isVersionOnOz and not WFOzDocUtils.doesDocumentNeedXmpDevelopSettingsUploaded( docValue )
				
				else
				
					local isValidOriginalAvailableOnOz = WFOzDocUtils.isValidOriginalAvailableOnOz( docValue )
					local isValidProxyAvailableOnOz = WFOzDocUtils.isValidProxyAvailableOnOz( docValue )
					
					shouldRemoveFiles = not keepRedactedBinaries or isValidOriginalAvailableOnOz or isValidProxyAvailableOnOz
				
				end
			
			else
			
				shouldRemoveFiles = true
				
			end
		
			if shouldRemoveFiles then
			
				-- Each entry within the purge list for proxies looks like this..
				-- localId = { <proxy size>, <proxy size>, .. }
				-- ..where <proxy size> is the size of a purgeable proxy within that
				-- specific document. Valid sizes include '2560', '1080p', 'panorama', etc.
			
				-- Similarly, each entry within the purge list for aux objects looks like this..
				-- localId = { <fingerprint>, fingerprint>, .. }
				-- ..where <fingerprint> is the fingerprint of a purgeable aux object.
			
				local specifiedProxySizesOrAuxFingerprints = purgeList[ docValue._localId ]
				
				if type( specifiedProxySizesOrAuxFingerprints ) ~= 'table' then
					specifiedProxySizesOrAuxFingerprints = nil
				end
			
				local localFilePaths, assetOverlay = WFCatDelete.filePathsToDeleteAndOverlays( 
						wfCatalog, docValue, binaryTypesToPurge, binaryTypesToDerefence, baseBinariesPath,
						specifiedProxySizesOrAuxFingerprints, specifiedProxySizesOrAuxFingerprints )
						
				if next( localFilePaths ) then
					
					logger:infof( "Will purge files for document %s", docValue._id )
					
					filePathsToDelete[ #filePathsToDelete + 1 ] = localFilePaths
				
				end
			
				if needToUpdateDocValue and assetOverlay then
					
					logger:infof( "Will update overlay for document %s", docValue._id )
				
					overlays[ #overlays + 1 ] = assetOverlay
					
				end
			
			end 
		
		end
		
		return filePathsToDelete, {}, overlays

	end 
	
	--------------------------------------------------------------------------------

	deleteFilePaths = function( catalog, filePathsToDelete )
	
		local deletionBacklog
		
		if not WFPlatformInfo.isClassic() and not WFCatPurgeHelper.DEBUG_optOutDeletionBacklog then
			deletionBacklog = catalog:getDeletionBacklog() or nil
		end
		
		for _, filePathsOfOneDoc in pairs( filePathsToDelete ) do
			WFCatDelete.deleteDocStoreFileArray( filePathsOfOneDoc, deletionBacklog, nil, true )
		end
	
	end
	
else
	
	local allProxySizes = {
		-- All
		'fullsize',
		'panorama',
		'pano', -- delete from old location (pano is deprecated)
		'2560',
		-- Videos
		'1080p',
		'720p',
		'360p',
	}
	
	-- Mobile functions
	
	getFilePathsToDeleteAndOverlay = function( wfCatalog, baseBinariesPath,
			docValues, purgeList, binaryTypesToPurge, needToUpdateDocValue,
			keepRedactedBinaries, binaryTypesToDerefence,
			deletingForSpaceOperation )
	
		binaryTypesToPurge = binaryTypesToPurge or {}
		binaryTypesToDerefence = binaryTypesToDerefence or {}
	
		local filePathsToDelete = {}
		local cacheEntriesToDelete = {}
		local overlays = {}
	
		for _, docValue in pairs( docValues ) do
		
			local shouldRemoveFiles = false
			
			if deletingForSpaceOperation then
			
				-- The following checks are only necessary if the purge operation is being triggered
				-- via the shared space workflows. Purge operations triggered via the purge agent
				-- perform similar checks prior to calling WFCatPurgeHelper.
			
				if docValue.type == 'version' then
			
					-- WF-1394: Prevent removing unsynced Version binaries. This allows us to resync these
					-- versions if the user is promoted to editor once again.
					
					local isVersionOnOz = KSTableUtils_derefOpt( docValue, '_serverProvidedMetadata', 'links' ) ~= nil
				
					shouldRemoveFiles = isVersionOnOz and not WFOzDocUtils.doesDocumentNeedXmpDevelopSettingsUploaded( docValue )
				
				else
				
					local isValidOriginalAvailableOnOz = WFOzDocUtils.isValidOriginalAvailableOnOz( docValue )
					local isValidProxyAvailableOnOz = WFOzDocUtils.isValidProxyAvailableOnOz( docValue )
				
					shouldRemoveFiles = not keepRedactedBinaries or isValidOriginalAvailableOnOz or isValidProxyAvailableOnOz
				
				end
				
			else
			
				shouldRemoveFiles = true
			
			end
			
			if shouldRemoveFiles then
		
				local overlay = {}
			
				local function processBinary( shouldPurge, binaryType, maybeIdentifier )
					
					local path = LrmOzPurgeAgentUtils.renditionPath( docValue, binaryType, maybeIdentifier )

					if path and path ~= '' then
					
						logger:infof( "Will purge files for document %s", docValue._id )
					
						if shouldPurge then
						
							if WFPlatformInfo.isAndroid 
									and ( binaryType == 'thumbnail2x'
											or binaryType == 'preview'
											or binaryType == 'fullsize' ) then
								
								cacheEntriesToDelete[ #cacheEntriesToDelete + 1 ] = path 
							
							else
							
								filePathsToDelete[ #filePathsToDelete + 1 ] = path
							
							end
							
						end
						
						if needToUpdateDocValue then
							
							logger:infof( "Will update overlay for document %s", docValue._id )
							
							overlay = LrmOzPurgeAgentUtils.updateOverlayWithRenditionName( overlay, binaryType, maybeIdentifier )
						
						end
						
					end
				
				end
			
				local function processBinaryType( binaryType, shouldPurge )
				
					if binaryType == 'proxy' then
				
						local specifiedProxySizes = purgeList[ docValue._localId ]
				
						if type( specifiedProxySizes ) ~= 'table' then
							specifiedProxySizes = false
						end
				
						local proxySizes = specifiedProxySizes or allProxySizes
						
						for _, size in ipairs( proxySizes ) do
							processBinary( shouldPurge, binaryType, size )
						end
					
					elseif binaryType == 'xmp_develop' then
					
						processBinary( shouldPurge, binaryType )
					
					elseif binaryType == 'aux' then
					
						local specifiedFingerprints = purgeList[ docValue._localId ]
						
						if type( specifiedFingerprints ) ~= 'table' then
							specifiedFingerprints = false
						end
						
						local extractDevelopAndC2paAux = WFTableMerge.applyOverlay(
							WFCatAssetAux.extractDevelopAuxDigestsFromDocValue( docValue ),
							WFCatAssetAux.extractC2paAuxDigestFromDocValue( docValue )
						)

						local auxFingerprints = specifiedFingerprints or extractDevelopAndC2paAux
			
						for _, fingerprint in pairs( auxFingerprints ) do
						
							processBinary( shouldPurge, 'aux', fingerprint )
							
						end
					
					else
					
						processBinary( shouldPurge, binaryType )
						
					end
				
				end
			
				for _, binaryType in pairs( binaryTypesToPurge ) do
				
					processBinaryType( binaryType, true )
					
				end
			
				for _, binaryType in pairs( binaryTypesToDerefence ) do
				
					processBinaryType( binaryType, false )
					
				end
			
				if next( overlay ) then
					
					overlay._id = docValue._id
					
					overlays[ #overlays + 1 ] = overlay
			
				end
				
			end
			
		end
	
		return filePathsToDelete, cacheEntriesToDelete, overlays
	
	end
	
	--------------------------------------------------------------------------------

	deleteFilePaths = function( catalog, filePathsToDelete )
	
		for _, filePath in pairs( filePathsToDelete ) do

			local absolutePath = LrmOzPurgeAgentUtils.absolutePath( catalog:ozCatalogId(), filePath )

			WFFileUtils.deleteFile( absolutePath )

			maybeDeleteAuxParentFolder( absolutePath )

		end

	end

end

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

--[[!

	Note:

	binaryTypesToPurge (optional table) A table of binaries whose annotations
		should be deleted from the document, and should also be removed from disk.
		
	binaryTypesToDerefence (optional table) A table of binaries whose annotations
		should be deleted from the document, but the binaries should *not*
		be removed from disk.

--]]

local function deleteFilesInPurgeList(
		catalog, purgeList, binaryTypesToDelete, needToUpdateDocValue, 
		keepRedactedBinaries, optDataCache, binaryTypesToDerefence,
		deletingForSpaceOperation )

	check( 'WFCatalog', 'table', '?table', '?boolean', '?boolean', '?KSDataCache', '?table', '?boolean' )

	local docStore = catalog:docStore()

	local wfCatFileSpec = catalog:fileSpec()
	
	local baseBinariesPath = wfCatFileSpec:catalogPath()

	local localIds = KSTableUtils.extractKeys( purgeList )

	logger:infof( "Now purging %s for %d documents", binaryTypesToDelete, #localIds )

	localIds.simplifyDeletedDocs = false

	return WFRxThrottledBatchedBulkDocValue( "WFCatPurgeHelper_deleteFilesByDocIds", docStore, localIds, 100, 10 )
			
		:map( function( assetDocValues )
		
			local filePathsToDelete, cacheEntriesToDelete, assetOverlays 
					= getFilePathsToDeleteAndOverlay(
							catalog, baseBinariesPath, assetDocValues, purgeList,
							binaryTypesToDelete, needToUpdateDocValue,
							keepRedactedBinaries, binaryTypesToDerefence,
							deletingForSpaceOperation )
			
			return filePathsToDelete, cacheEntriesToDelete, assetOverlays
		
		end )
		
		:scan( function( filePathsToDelete, cacheEntriesToDelete, overlays, 
							batchOfFilePathsToDelete, batchOfCacheEntriesToDelete, batchOfOverlays )
		
			filePathsToDelete = KSTableUtils_appendArray( filePathsToDelete, batchOfFilePathsToDelete )
			cacheEntriesToDelete = KSTableUtils_appendArray( cacheEntriesToDelete, batchOfCacheEntriesToDelete )
			overlays = KSTableUtils_appendArray( overlays, batchOfOverlays )
			
			return filePathsToDelete, cacheEntriesToDelete, overlays
			
		end, {}, {}, {} )
		
		:takeLast( 1 ) 
		
		:flatMap( function( filePathsToDelete, cacheEntriesToDelete, overlays )
		
			-- delete filePaths
			
			logger:info( "Now deleting file paths..." )
			
			deleteFilePaths( catalog, filePathsToDelete )

			-- delete cacheEntries
			
			logger:info( "Now clearing cache entries..." )
			
			local result = Observable.just( true )
			
			if optDataCache and #cacheEntriesToDelete > 0 then
			
				result = optDataCache:removeBulk( cacheEntriesToDelete )
				
			end 
			
			-- apply overlays
			
			logger:info( "Now applying overlays..." )
			
			if #overlays == 0 or not needToUpdateDocValue then
				return result
			end
			
			return result
				:flatMap( function()
					return WFRxThrottledBatchedBulkApplyOverlay( 'WFCatPurgeHelper_deleteFilesByDocIds', docStore, overlays, 100, 10 )
				end )
				
		end )

end

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

local function maybeClearRecentlyDownloadedStatusForBinaries( idleDownloader, purgeList, binaryTypesToDelete )

	if idleDownloader then

		for localId in pairs( purgeList ) do

			for _, binaryType in ipairs( binaryTypesToDelete ) do
			
				idleDownloader:clearRecentlyDownloadedStatus( localId, binaryType )
					-- Allow the asset to be immediately redownloaded, if needed.
					
			end

		end
	
	end

end

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

local function createPurgeListFromDocIds( docIds )

	-- Converts a docIds table to the purgeList format.
	
	local purgeList = {}
	
	for _, docId in ipairs( docIds ) do
		purgeList[ docId ] = true
	end
	
	return purgeList

end

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

local function createPurgeFunctionForBinaryTypes( binaryTypesToDelete )

	local fn = function( catalog, purgeList, optIdleDownloader, optDataCache )
	
		if not purgeList then
			return Observable.empty()
		end
		
		local needToUpdateDocValue = true
		local keepRedactedBinaries = false

		return deleteFilesInPurgeList( catalog, purgeList, binaryTypesToDelete, 
				needToUpdateDocValue, keepRedactedBinaries, optDataCache )

			:map( function()
			
				maybeClearRecentlyDownloadedStatusForBinaries(
						optIdleDownloader, purgeList, binaryTypesToDelete )
			
				return true
			
			end )
	
	end

	return fn

end

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

local function deleteAndDereferenceAuxiliariesForSpace(
		catalog, spaceId, docIds, purgeList, needToUpdateDocValue, 
		keepRedactedBinaries, deletingForSpaceOperation, optDataCache )

	-- Special handling for auxiliaries, since we only want to delete
	-- auxiliaries that are not shared outside of this space.
	
	return WFCatVolumeAgentQueryHelper.getAuxPurgeListForDeletedOrDowngradedSpace( 
			catalog, spaceId, docIds )
			
		:flatMap( function( auxPurgeList )

			-- Delete the auxiliaries that are NOT shared outside of the space.
			
			return deleteFilesInPurgeList( catalog, auxPurgeList, { 'aux' }, 
					needToUpdateDocValue, keepRedactedBinaries, optDataCache,
					nil, deletingForSpaceOperation )

		end )
		
		:flatMap( function()

			-- Dereference the remaining auxiliaries that are shared outside
			-- of the space.
			
			return deleteFilesInPurgeList( catalog, purgeList, nil, 
					needToUpdateDocValue, keepRedactedBinaries, optDataCache,
					{ 'aux' }, deletingForSpaceOperation )

		end )
		
end

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

-- All platform are able to purge originals, proxies, develop settings, as well
-- as aux objects (masks).

local purgeFunctionByBinaryType = {

	original = createPurgeFunctionForBinaryTypes( { 'original', 'xmp', 'latestOriginal' } ),
	proxy = createPurgeFunctionForBinaryTypes( { 'proxy' } ),
	xmp_develop = createPurgeFunctionForBinaryTypes( { 'xmp_develop'} ),
	aux = createPurgeFunctionForBinaryTypes( { 'aux'} )
	
}

-- Only mobile clients additionally purge renditions

if WFPlatformInfo.isMobile() then

	purgeFunctionByBinaryType.fullsize = createPurgeFunctionForBinaryTypes( { 'fullsize' } )
	purgeFunctionByBinaryType.preview = createPurgeFunctionForBinaryTypes( { 'preview' } )
	purgeFunctionByBinaryType.thumbnail2x = createPurgeFunctionForBinaryTypes( { 'thumbnail2x' } )
	
end

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

-- @mark APIs

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

--[[!

	\brief Deletes the binaries associated with the assets in the purge lists
		from the device.
	
	\param docStore (WFRxDocStore)
	\param purgeList (table) A table containing nested tables, which contain
		asset ids (local Ids) and the associated binary types to remove. 
		Example structure:
	
		{
			{
				binaryType = 'original',
				localId = true,
				localId = true,
				...
			},
			{
				binaryType = 'proxy',
				localId = { '2560', 'pano', ... },
				localId = { '720p', '1080p', ... },
				...
			},
			{
				binaryType = 'xmp_develop'
				localId = true,
				localId = true,
				...
			},
			{
				binaryType = 'aux'
				localId = { aux1_fingerprint, aux2_fingerprint, ... },
				localId = { aux1_fingerprint, aux2_fingerprint, ... },
				...
			},
			{
				binaryType = 'fullsize'
				localId = true,
				localId = true,
				...
			},
			{
				binaryType = 'preview'
				localId = true,
				localId = true,
				...
			},
			{
				binaryType = 'thumbnail2x'
				localId = true,
				localId = true,
				...
			}		
		}
	
	\param maybeIdleDownloader (WFCatIdleDownloader) Must be provided for Desktop.
	\param optDataCache (KSDataCache) Must be provided for Android.
 
	\return (Observable) Completes once the binaries within the purge lists
		have been deleted from the device. If an unknown binary type is encountered,
		an error is thrown.

--]]

function WFCatPurgeHelper.deleteFilesByPurgeList( catalog, purgeList, optIdleDownloader, optDataCache )

	check( 'WFCatalog', 'table', '?WFCatIdleDownloader', '?KSDataCache' )

	local deletionObs = Observable.just( true )

	for _, purgeListForType in ipairs( purgeList ) do

		local binaryType = purgeListForType.binaryType
		purgeListForType.binaryType = nil
		
		local fn = purgeFunctionByBinaryType[ binaryType ]

		if fn then
		
			deletionObs = deletionObs:concat( fn( catalog, purgeListForType, optIdleDownloader, optDataCache ) )
			
		else
		
			local errorMessage = string.format( "Not sure how to purge %d binaries of type %s.", 
					#purgeListForType, binaryType )
					
			logger:error( errorMessage )
					
			return Observable.throw( errorMessage )
		
		end
		
	end

	return deletionObs:takeLast( 0 )

end

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

--[[!

	\brief Deletes the binaries associated with the associated Asset document Ids.
	
	Note: This function does not purge xmp_develop settings for LrD because
	they can be shared between documents. The purging of these settings
	is handled by the pixel provider (PixelProviderFileCachePurgeWorker).
	
	\param docStore (WFRxDocStore)
	\param docIds (table)
	\param needToUpdateDocValue (boolean)
	\param keepRedactedBinaries (boolean)
	\param optDataCache (KSDataCache) Must be provided for Android.
 
	\return (Observable) Completes once the files have been deleted.
	
--]]

function WFCatPurgeHelper.deleteAssetFilesByDocIdsForSpace( 
		catalog, spaceId, docIds, needToUpdateDocValue, keepRedactedBinaries, optDataCache )

	check( 'WFCatalog', '+string', 'table', '?boolean', '?boolean', '?KSDataCache' )

	local binaryTypesToPurge
	local binaryTypesToDerefence
	
	if WFPlatformInfo.isDesktop then
	
		binaryTypesToPurge =  { 'original', 'proxy', 'xmp' }
		binaryTypesToDerefence = { 'xmp_develop' }

	else

		binaryTypesToPurge = { 'original', 'latestOriginal', 'proxy', 'xmp_develop' }

		if not keepRedactedBinaries then

			binaryTypesToPurge = { 'original', 'latestOriginal', 'proxy', 'xmp_develop', 'thumbnail2x', 'preview', 'fullsize' }

		end
	
	end
	
	local purgeList = createPurgeListFromDocIds( docIds )
	
	local deletingForSpaceOperation = true

	return deleteFilesInPurgeList( catalog, purgeList, binaryTypesToPurge, 
			needToUpdateDocValue, keepRedactedBinaries, optDataCache,
			binaryTypesToDerefence, deletingForSpaceOperation )
			
		:flatMap( function()

			-- Special handling for auxiliaries, since we only want to delete
			-- auxiliaries that are not shared outside of this space.

			return deleteAndDereferenceAuxiliariesForSpace(
					catalog, spaceId, docIds, purgeList, needToUpdateDocValue, 
					keepRedactedBinaries, deletingForSpaceOperation, optDataCache )

		end )

end

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

--[[!

	\brief Deletes the binaries associated with the associated Version document Ids.
	
	Note: This function does not purge xmp_develop settings for LrD because
	they can be shared between documents. The purging of these settings
	is handled by the pixel provider (PixelProviderFileCachePurgeWorker).
	
	\param docStore (WFRxDocStore)
	\param docIds (table)
	\param needToUpdateDocValue (boolean)
	\param keepRedactedBinaries (boolean)
	\param optDataCache (KSDataCache) Must be provided for Android.
 
	\return (Observable) Completes once the files have been deleted.
	
--]]

function WFCatPurgeHelper.deleteVersionFilesByDocIdsForSpace( 
		catalog, spaceId, docIds, needToUpdateDocValue, keepRedactedBinaries, optDataCache )

	check( 'WFCatalog', '+string', 'table', '?boolean', '?boolean', '?KSDataCache' )

	local binaryTypesToPurge, binaryTypesToDerefence

	if WFPlatformInfo.isDesktop then
	
		-- On Desktop, we want to remove the xmp_develop annotations from the doc values,
		-- but keep the files on disk because they are shared between documents.

		binaryTypesToDerefence = { 'xmp_develop' }

	else

		binaryTypesToPurge = { 'xmp_develop', 'thumbnail2x' }

	end

	local purgeList = createPurgeListFromDocIds( docIds )

	local deletingForSpaceOperation = true

	return deleteFilesInPurgeList( catalog, purgeList, binaryTypesToPurge, 
			needToUpdateDocValue, keepRedactedBinaries, optDataCache,
			binaryTypesToDerefence, deletingForSpaceOperation )

		:flatMap( function()

			-- Special handling for auxiliaries, since we only want to delete
			-- auxiliaries that are not shared outside of this space.

			return deleteAndDereferenceAuxiliariesForSpace(
					catalog, spaceId, docIds, purgeList, needToUpdateDocValue, 
					keepRedactedBinaries, deletingForSpaceOperation, optDataCache )

		end )

end

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

return WFCatPurgeHelper
