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

WFCatSpacePurgeUtilsTest.lua

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

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.rxlua
local WFRxTestCase = require 'WFRxTestCase'

	-- WF.core.utils
local KSIdGenerator = require 'KSIdGenerator'
local KSTableUtils = require 'KSTableUtils'
local KSData = require 'KSData'
local WFPlatformInfo = require 'WFPlatformInfo'

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

	-- WF.oz_client.managed_catalog
local WFCatAssetUtils = require 'WFCatAssetUtils'
local WFCatVersions = require 'WFCatVersions'
local WFCatSpacePurgeUtils = require 'WFCatSpacePurgeUtils'
local WFCatMockCatalog = require 'WFCatMockCatalog'
local WFCatAssetTestUtils = require 'WFCatAssetTestUtils'
local LrmCatalogTestHelper

	-- WF.lrmobile.modules.source
local LrmOzPurgeAgentUtils

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

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

local derefOpt = assert( KSTableUtils.derefOpt )
local derefUniversal = assert( WFCatAssetUtils.derefUniversal )

local albumAssetTable = "album_asset"
if WFPlatformInfo.isDesktop then
	albumAssetTable = "album_asset_v2"
end

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

local WFCatSpacePurgeUtilsTest = {}

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

local function createFakeWFCatalog( rxTest )

	local optArgs = {}
		
	if WFPlatformInfo.isMobile() then
		optArgs.indexDefinitions = 'LrmCatalogIndexDefinitions.lua'
	end

	return WFCatMockCatalog.createFakeWFCatalog( rxTest , nil, nil, optArgs )

end

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

local function testPurgeAssetsForSpace_desktop( rxTest, keepRedactedBinaries, withRedactedOzLink, onlyHasProxyLink )

	rxTest:setTimeLimit( 10 )

	local wfCatalog = createFakeWFCatalog( rxTest )
	
	local assetId = KSIdGenerator.uuidInLowercaseHex()
	local spaceId = KSIdGenerator.uuidInLowercaseHex()
	
	local assetDocValue, expectedData = WFCatAssetTestUtils.createAssetDocument( rxTest, wfCatalog, assetId )
	assetDocValue._spaceId = spaceId
	
	if withRedactedOzLink then
		KSTableUtils.setNested( assetDocValue, nil, '_serverProvidedMetadata', 'links', '/rels/master', 'href' )
		KSTableUtils.setNested( assetDocValue, true, '_serverProvidedMetadata', 'links', '/rels/master', 'exists' )
		
		KSTableUtils.setNested( assetDocValue, nil, '_serverProvidedMetadata', 'links', '/rels/proxy_type/2560', 'href' )
		KSTableUtils.setNested( assetDocValue, true, '_serverProvidedMetadata', 'links', '/rels/proxy_type/2560', 'exists' )
	end
	
	if onlyHasProxyLink then
		KSTableUtils.setNested( assetDocValue, nil, '_serverProvidedMetadata', 'links', '/rels/master' )
	end
	
	rxTest:expectSingleValue( wfCatalog:docStore():setDocValue( assetDocValue ), ':ignore:' )
	
	-- check if all files exist
	-- xmp_develop purging on desktop would be handled by PixelProviderFileCachePurgeWorker
	
	rxTest:expectEqual( 'file', WFFileUtils.exists( expectedData.originalFilePath ) )
	rxTest:expectEqual( 'file', WFFileUtils.exists( expectedData.xmpSidecarFilePath ) )
	rxTest:expectEqual( 'file', WFFileUtils.exists( expectedData.proxyFilePath ) )

	-- create space and add asset into space
	
	local albumId = KSIdGenerator.uuidInLowercaseHex()
	
	local albumDoc = {

		_id = albumId,
		_spaceId = spaceId,
		type = 'album',
		subtype = 'collection',
		name = 'foo',

	}

	rxTest:expectSingleValue( wfCatalog:docStore():setDocValue( albumDoc ), ':ignore:' )
	
	local albumAssetId = KSIdGenerator.uuidInLowercaseHex()
	
	local albumAssetDoc = {

		_id = albumAssetId,
		_spaceId = spaceId,
		type = 'album_asset',
		asset = {
			id = assetId
		},
		album = {
			id = albumId
		}
	}
	
	rxTest:expectSingleValue( wfCatalog:docStore():setDocValue( albumAssetDoc ), ':ignore:' )

	rxTest:observe( wfCatalog:indexStore():query{
			sql = string.format( [[SELECT docId FROM %s WHERE albumId = ?]], albumAssetTable ),
			albumId
		})
		:expectDataWithinTime( 2, {{ 3 }} )
		:dispose()
	
	-- purge assets for space
	
	rxTest:waitFor( WFCatSpacePurgeUtils.DEBUG_purgeAssetsForSpace( wfCatalog, spaceId, true, keepRedactedBinaries ) )
	
	-- check if files are purged and doc is updated
	
	rxTest:expectEqual( false, WFFileUtils.exists( expectedData.originalFilePath ) )
	rxTest:expectEqual( false, WFFileUtils.exists( expectedData.xmpSidecarFilePath ) )
	rxTest:expectEqual( false, WFFileUtils.exists( expectedData.proxyFilePath ) )
	
	rxTest:expectSingleValue( wfCatalog:docStore():docValue( assetId )
		:map( function( assetDocValue )
			
			return derefOpt( assetDocValue, '_localOnly', 'files', 'original', 'master', 'relativePath' ) == nil
					and derefOpt( assetDocValue, '_localOnly', 'files', 'proxy', '2560', 'relativePath' ) == nil
					and derefOpt( assetDocValue, '_localOnly', 'files', 'original', 'xmp', 'path' ) == nil
			
		end ),
		true
	)

end 

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

local function testPurgeAssetsForSpace_iOS( rxTest, keepRedactedBinaries, withRedactedOzLink, onlyHasProxyLink )

	rxTest:setTimeLimit( 10 )

	local wfCatalog = createFakeWFCatalog( rxTest )
	
	local assetId = KSIdGenerator.uuidInLowercaseHex()
	local spaceId = KSIdGenerator.uuidInLowercaseHex()
	
	local assetDocValue, expectedData = WFCatAssetTestUtils.createAssetDocument( rxTest, wfCatalog, assetId )
	assetDocValue._spaceId = spaceId
	
	if withRedactedOzLink then
		KSTableUtils.setNested( assetDocValue, nil, '_serverProvidedMetadata', 'links', '/rels/master', 'href' )
		KSTableUtils.setNested( assetDocValue, true, '_serverProvidedMetadata', 'links', '/rels/master', 'exists' )
		
		KSTableUtils.setNested( assetDocValue, nil, '_serverProvidedMetadata', 'links', '/rels/proxy_type/2560', 'href' )
		KSTableUtils.setNested( assetDocValue, true, '_serverProvidedMetadata', 'links', '/rels/proxy_type/2560', 'exists' )
	end
	
	if onlyHasProxyLink then
		KSTableUtils.setNested( assetDocValue, nil, '_serverProvidedMetadata', 'links', '/rels/master' )
	end
	
	rxTest:expectSingleValue( wfCatalog:docStore():setDocValue( assetDocValue ), ':ignore:' )
	
	-- check if all files exist
	
	rxTest:expectEqual( 'file', WFFileUtils.exists( expectedData.originalFilePath ) )
	rxTest:expectEqual( 'file', WFFileUtils.exists( expectedData.proxyFilePath ) )
	rxTest:expectEqual( 'file', WFFileUtils.exists( expectedData.previewFilePath ) )
	rxTest:expectEqual( 'file', WFFileUtils.exists( expectedData.thumbnailFilePath ) )
	rxTest:expectEqual( 'file', WFFileUtils.exists( expectedData.xmpDevelopSettingsFilePath ) )

	-- create space and add asset into space
	
	local albumId = KSIdGenerator.uuidInLowercaseHex()
	
	local albumDoc = {

		_id = albumId,
		_spaceId = spaceId,
		type = 'album',
		subtype = 'collection',
		name = 'foo',

	}

	rxTest:expectSingleValue( wfCatalog:docStore():setDocValue( albumDoc ), ':ignore:' )
	
	local albumAssetId = KSIdGenerator.uuidInLowercaseHex()
	
	local albumAssetDoc = {

		_id = albumAssetId,
		_spaceId = spaceId,
		type = 'album_asset',
		asset = {
			id = assetId
		},
		album = {
			id = albumId
		}
	}
	
	rxTest:expectSingleValue( wfCatalog:docStore():setDocValue( albumAssetDoc ), ':ignore:' )

	rxTest:observe( wfCatalog:indexStore():query{
			sql = string.format( [[SELECT docId FROM %s WHERE albumId = ?]], albumAssetTable ),
			albumId
		})
		:expectDataWithinTime( 2, {{ albumAssetId }} )
		:dispose()
	
	-- purge assets for space
	
	rxTest:waitFor( WFCatSpacePurgeUtils.DEBUG_purgeAssetsForSpace( wfCatalog, spaceId, true, keepRedactedBinaries ) )
	
	-- check if files are purged and doc is updated
	
	rxTest:expectEqual( false, WFFileUtils.exists( expectedData.originalFilePath ) )
	rxTest:expectEqual( false, WFFileUtils.exists( expectedData.proxyFilePath ) )
	rxTest:expectEqual( false, WFFileUtils.exists( expectedData.xmpDevelopSettingsFilePath ) )
	
	if not keepRedactedBinaries then
		rxTest:expectEqual( false, WFFileUtils.exists( expectedData.previewFilePath ) )
		rxTest:expectEqual( false, WFFileUtils.exists( expectedData.thumbnailFilePath ) )
	end
	
	rxTest:expectSingleValue( wfCatalog:docStore():docValue( assetId )
		:map( function( assetDocValue )
			
			local check = derefUniversal( assetDocValue, 'files', 'original', 'master', 'relativePath' ) == nil
							and derefUniversal( assetDocValue, 'files', 'proxy', '2560', 'relativePath' ) == nil
							and derefUniversal( assetDocValue, 'files', 'xmp_develop', 'relativePath' ) == nil
			
			if keepRedactedBinaries then
				return check
			else
			
				return check
					and derefUniversal( assetDocValue, 'files', 'renditions', 'thumbnail2x', 'relativePath' ) == nil
					and derefUniversal( assetDocValue, 'files', 'renditions', '2048', 'relativePath' ) == nil
			
			end
			
		end ),
		true
	)

end 

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

local function testPurgeAssetsForSpace_android( rxTest, keepRedactedBinaries, withRedactedOzLink, onlyHasProxyLink )

	rxTest:setTimeLimit( 10 )

	local catalogService, wfCatalog = LrmCatalogTestHelper.makeCatalogService()
	local catalogDataCache
	
	local assetId = KSIdGenerator.uuidInLowercaseHex()
	local spaceId = KSIdGenerator.uuidInLowercaseHex()
	
	local assetDocValue, expectedData = WFCatAssetTestUtils.createAssetDocument( rxTest, wfCatalog, assetId )

	-- add preview and thumbnail2xData into dataCache
	
	local previewData = KSData.memoryMappedContentsOfFile( expectedData.previewFilePath )
	local thumbnail2xData = KSData.memoryMappedContentsOfFile( expectedData.thumbnailFilePath )

	local previewMd5 = previewData:digest( 'MD5' )
	local thumbMd5 = thumbnail2xData:digest( 'MD5' )
	
	rxTest:expectSingleValue( catalogService:getDataCache()
		:flatMap( function( dataCache )
			catalogDataCache = dataCache
			return dataCache:put( previewMd5, previewData )
		end )
		:map( tostring ),
		tostring( previewData ) )
		
	rxTest:expectSingleValue( catalogService:getDataCache()
		:flatMap( function( dataCache )
			return dataCache:put( thumbMd5, thumbnail2xData )
		end )
		:map( tostring ),
		tostring( thumbnail2xData ) )
		
	-- add asset into docStore
	
	assetDocValue._spaceId = spaceId
	
	if withRedactedOzLink then
		KSTableUtils.setNested( assetDocValue, nil, '_serverProvidedMetadata', 'links', '/rels/master', 'href' )
		KSTableUtils.setNested( assetDocValue, true, '_serverProvidedMetadata', 'links', '/rels/master', 'exists' )
		
		KSTableUtils.setNested( assetDocValue, nil, '_serverProvidedMetadata', 'links', '/rels/proxy_type/2560', 'href' )
		KSTableUtils.setNested( assetDocValue, true, '_serverProvidedMetadata', 'links', '/rels/proxy_type/2560', 'exists' )
	end
	
	if onlyHasProxyLink then
		KSTableUtils.setNested( assetDocValue, nil, '_serverProvidedMetadata', 'links', '/rels/master' )
	end
	
	rxTest:expectSingleValue( wfCatalog:docStore():setDocValue( assetDocValue ), ':ignore:' )
		
	-- check if all files exist
	
	rxTest:expectEqual( 'file', WFFileUtils.exists( expectedData.originalFilePath ) )
	rxTest:expectEqual( 'file', WFFileUtils.exists( expectedData.proxyFilePath ) )
	rxTest:expectEqual( 'file', WFFileUtils.exists( expectedData.xmpDevelopSettingsFilePath ) )

	rxTest:expectSingleValue( catalogService:getDataCache()
		:flatMap( function( dataCache )
			return dataCache:get( previewMd5 )
		end )
		:map( tostring ),
		tostring( previewData ) )
		
	rxTest:expectSingleValue( catalogService:getDataCache()
		:flatMap( function( dataCache )
			return dataCache:get( thumbMd5 )
		end )
		:map( tostring ),
		tostring( thumbnail2xData ) )

	-- create space and add asset into space
	
	local albumId = KSIdGenerator.uuidInLowercaseHex()
	
	local albumDoc = {

		_id = albumId,
		_spaceId = spaceId,
		type = 'album',
		subtype = 'collection',
		name = 'foo',

	}

	rxTest:expectSingleValue( wfCatalog:docStore():setDocValue( albumDoc ), ':ignore:' )
	
	local albumAssetId = KSIdGenerator.uuidInLowercaseHex()
	
	local albumAssetDoc = {

		_id = albumAssetId,
		_spaceId = spaceId,
		type = 'album_asset',
		asset = {
			id = assetId
		},
		album = {
			id = albumId
		}
	}
	
	rxTest:expectSingleValue( wfCatalog:docStore():setDocValue( albumAssetDoc ), ':ignore:' )

	rxTest:observe( wfCatalog:indexStore():query{
			sql = string.format( [[SELECT docId FROM %s WHERE albumId = ?]], albumAssetTable ),
			albumId
		})
		:expectDataWithinTime( 2, {{ albumAssetId }} )
		:dispose()
	
	-- purge assets for space
	
	rxTest:waitFor( WFCatSpacePurgeUtils.DEBUG_purgeAssetsForSpace( wfCatalog, spaceId, true, keepRedactedBinaries, catalogDataCache ) )
	
	-- check if files are purged and doc is updated
	
	rxTest:expectEqual( false, WFFileUtils.exists( expectedData.originalFilePath ) )
	rxTest:expectEqual( false, WFFileUtils.exists( expectedData.proxyFilePath ) )
	rxTest:expectEqual( false, WFFileUtils.exists( expectedData.xmpDevelopSettingsFilePath ) )
	
	if not keepRedactedBinaries then
	
		rxTest:expectSingleValue( catalogService:getDataCache()
			:flatMap( function( dataCache )
				return dataCache:get( previewMd5 )
			end ),
			nil )
			
		rxTest:expectSingleValue( catalogService:getDataCache()
			:flatMap( function( dataCache )
				return dataCache:get( thumbMd5 )
			end ),
			nil )
	
	end
	
	rxTest:expectSingleValue( wfCatalog:docStore():docValue( assetId )
		:map( function( assetDocValue )
			
			local check = derefUniversal( assetDocValue, 'files', 'original', 'master', 'relativePath' ) == nil
							and derefUniversal( assetDocValue, 'files', 'proxy', '2560', 'relativePath' ) == nil
							and derefUniversal( assetDocValue, 'files', 'xmp_develop', 'relativePath' ) == nil
			
			if keepRedactedBinaries then
				return check
			else
			
				return check
					and derefUniversal( assetDocValue, 'files', 'renditions', 'thumbnail2x', 'relativePath' ) == nil
					and derefUniversal( assetDocValue, 'files', 'renditions', '2048', 'relativePath' ) == nil
			
			end
			
		end ),
		true
	)

	previewData:close()
	thumbnail2xData:close()

end 

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

function WFCatSpacePurgeUtilsTest.rxTestPurgeAssetsForSpace( rxTest )

	local keepRedactedBinaries = false
	local withRedactedOzLink = false
	local onlyHasProxyLink = false
	
	if WFPlatformInfo.isDesktop then
	
		testPurgeAssetsForSpace_desktop( rxTest, keepRedactedBinaries, withRedactedOzLink, onlyHasProxyLink )
		
	elseif WFPlatformInfo.isiOS then
	
		testPurgeAssetsForSpace_iOS( rxTest, keepRedactedBinaries, withRedactedOzLink, onlyHasProxyLink )
		
	elseif WFPlatformInfo.isAndroid then
	
		testPurgeAssetsForSpace_android( rxTest, keepRedactedBinaries, withRedactedOzLink, onlyHasProxyLink )
		
	end

end

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

function WFCatSpacePurgeUtilsTest.rxTestPurgeAssetsForSpace_WithRedactedMaterLink( rxTest )

	local keepRedactedBinaries = false
	local withRedactedOzLink = true
	local onlyHasProxyLink = false
	
	if WFPlatformInfo.isDesktop then
	
		testPurgeAssetsForSpace_desktop( rxTest, keepRedactedBinaries, withRedactedOzLink, onlyHasProxyLink )
		
	elseif WFPlatformInfo.isiOS then
	
		testPurgeAssetsForSpace_iOS( rxTest, keepRedactedBinaries, withRedactedOzLink, onlyHasProxyLink )
		
	elseif WFPlatformInfo.isAndroid then
	
		testPurgeAssetsForSpace_android( rxTest, keepRedactedBinaries, withRedactedOzLink, onlyHasProxyLink )
		
	end

end

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

function WFCatSpacePurgeUtilsTest.rxTestPurgeAssetsForSpace_KeepRedactedBinaries( rxTest )

	local keepRedactedBinaries = true
	local withRedactedOzLink = false
	local onlyHasProxyLink = false
	
	if WFPlatformInfo.isDesktop then
	
		testPurgeAssetsForSpace_desktop( rxTest, keepRedactedBinaries, withRedactedOzLink, onlyHasProxyLink )
		
	elseif WFPlatformInfo.isiOS then
	
		testPurgeAssetsForSpace_iOS( rxTest, keepRedactedBinaries, withRedactedOzLink, onlyHasProxyLink )
		
	elseif WFPlatformInfo.isAndroid then
	
		testPurgeAssetsForSpace_android( rxTest, keepRedactedBinaries, withRedactedOzLink, onlyHasProxyLink )
		
	end

end

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

function WFCatSpacePurgeUtilsTest.rxTestPurgeAssetsForSpace_KeepRedactedBinaries_WithRedactedMaterLink( rxTest )

	local keepRedactedBinaries = true
	local withRedactedOzLink = true
	local onlyHasProxyLink = false
	
	if WFPlatformInfo.isDesktop then
	
		testPurgeAssetsForSpace_desktop( rxTest, keepRedactedBinaries, withRedactedOzLink, onlyHasProxyLink )
		
	elseif WFPlatformInfo.isiOS then
	
		testPurgeAssetsForSpace_iOS( rxTest, keepRedactedBinaries, withRedactedOzLink, onlyHasProxyLink )
		
	elseif WFPlatformInfo.isAndroid then
	
		testPurgeAssetsForSpace_android( rxTest, keepRedactedBinaries, withRedactedOzLink, onlyHasProxyLink )
		
	end

end

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

function WFCatSpacePurgeUtilsTest.rxTestPurgeAssetsForSpace_KeepRedactedBinaries_onlyHasProxyLink( rxTest )

	local keepRedactedBinaries = true
	local withRedactedOzLink = false
	local onlyHasProxyLink = true
	
	if WFPlatformInfo.isDesktop then
	
		testPurgeAssetsForSpace_desktop( rxTest, keepRedactedBinaries, withRedactedOzLink, onlyHasProxyLink )
		
	elseif WFPlatformInfo.isiOS then
	
		testPurgeAssetsForSpace_iOS( rxTest, keepRedactedBinaries, withRedactedOzLink, onlyHasProxyLink )
		
	elseif WFPlatformInfo.isAndroid then
	
		testPurgeAssetsForSpace_android( rxTest, keepRedactedBinaries, withRedactedOzLink, onlyHasProxyLink )
		
	end

end

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

function WFCatSpacePurgeUtilsTest.rxTestPurgeAssetsForSpace_KeepRedactedBinaries_OnlyHasProxyRedactedLink( rxTest )

	local keepRedactedBinaries = true
	local withRedactedOzLink = true
	local onlyHasProxyLink = true
	
	if WFPlatformInfo.isDesktop then
	
		testPurgeAssetsForSpace_desktop( rxTest, keepRedactedBinaries, withRedactedOzLink, onlyHasProxyLink )
		
	elseif WFPlatformInfo.isiOS then
	
		testPurgeAssetsForSpace_iOS( rxTest, keepRedactedBinaries, withRedactedOzLink, onlyHasProxyLink )
		
	elseif WFPlatformInfo.isAndroid then
	
		testPurgeAssetsForSpace_android( rxTest, keepRedactedBinaries, withRedactedOzLink, onlyHasProxyLink )
		
	end

end

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

function WFCatSpacePurgeUtilsTest.rxTestPurgeAssetsForSpace_EditorDowngradWithBinariesNotUploaded( rxTest )

	rxTest:setTimeLimit( 10 )

	local wfCatalog = createFakeWFCatalog( rxTest )
	
	local assetId = KSIdGenerator.uuidInLowercaseHex()
	local spaceId = KSIdGenerator.uuidInLowercaseHex()
	
	local assetDocValue, expectedData = WFCatAssetTestUtils.createAssetDocument( rxTest, wfCatalog, assetId )
	assetDocValue._spaceId = spaceId
	assetDocValue._serverProvidedMetadata = nil
	
	rxTest:expectSingleValue( wfCatalog:docStore():setDocValue( assetDocValue ), ':ignore:' )
	
	-- check if all files exist
	
	if WFPlatformInfo.isDesktop then
	
		rxTest:expectEqual( 'file', WFFileUtils.exists( expectedData.originalFilePath ) )
		rxTest:expectEqual( 'file', WFFileUtils.exists( expectedData.xmpSidecarFilePath ) )
		rxTest:expectEqual( 'file', WFFileUtils.exists( expectedData.proxyFilePath ) )
	
	else
	
		rxTest:expectEqual( 'file', WFFileUtils.exists( expectedData.originalFilePath ) )
		rxTest:expectEqual( 'file', WFFileUtils.exists( expectedData.proxyFilePath ) )
		rxTest:expectEqual( 'file', WFFileUtils.exists( expectedData.xmpDevelopSettingsFilePath ) )
		
	end

	-- create space and add asset into space
	
	local albumId = KSIdGenerator.uuidInLowercaseHex()
	
	local albumDoc = {

		_id = albumId,
		_spaceId = spaceId,
		type = 'album',
		subtype = 'collection',
		name = 'foo',

	}

	rxTest:expectSingleValue( wfCatalog:docStore():setDocValue( albumDoc ), ':ignore:' )
	
	local albumAssetId = KSIdGenerator.uuidInLowercaseHex()
	
	local albumAssetDoc = {

		_id = albumAssetId,
		_spaceId = spaceId,
		type = 'album_asset',
		asset = {
			id = assetId
		},
		album = {
			id = albumId
		}
	}
	
	rxTest:expectSingleValue( wfCatalog:docStore():setDocValue( albumAssetDoc ), ':ignore:' )

	local expectedAlbumAssetDocId = albumAssetId
	if WFPlatformInfo.isDesktop then
		expectedAlbumAssetDocId = 3
	end
	
	rxTest:observe( wfCatalog:indexStore():query{
			sql = string.format( [[SELECT docId FROM %s WHERE albumId = ?]], albumAssetTable ),
			albumId
		})
		:expectDataWithinTime( 2, {{ expectedAlbumAssetDocId }} )
		:dispose()
	
	-- purge assets for space
	
	rxTest:waitFor( WFCatSpacePurgeUtils.DEBUG_purgeAssetsForSpace( wfCatalog, spaceId, true, true ) )
	
	-- check if original, proxy and xmp_develop files still exists
	
	if WFPlatformInfo.isDesktop then
	
		rxTest:expectEqual( 'file', WFFileUtils.exists( expectedData.originalFilePath ) )
		rxTest:expectEqual( 'file', WFFileUtils.exists( expectedData.xmpSidecarFilePath ) )
		rxTest:expectEqual( 'file', WFFileUtils.exists( expectedData.proxyFilePath ) )
	
	else
	
		rxTest:expectEqual( 'file', WFFileUtils.exists( expectedData.originalFilePath ) )
		rxTest:expectEqual( 'file', WFFileUtils.exists( expectedData.proxyFilePath ) )
		rxTest:expectEqual( 'file', WFFileUtils.exists( expectedData.xmpDevelopSettingsFilePath ) )
		
	end
	
	rxTest:expectSingleValue( wfCatalog:docStore():docValue( assetId )
		:map( function( assetDocValue )
			
			if WFPlatformInfo.isDesktop then
			
				return derefOpt( assetDocValue, '_localOnly', 'files', 'original', 'master', 'relativePath' ) ~= nil
					and derefOpt( assetDocValue, '_localOnly', 'files', 'proxy', '2560', 'relativePath' ) ~= nil
					and derefOpt( assetDocValue, '_localOnly', 'files', 'original', 'xmp', 'path' ) ~= nil
			
			else
			
				return derefUniversal( assetDocValue, 'files', 'original', 'master', 'relativePath' ) ~= nil
					and derefUniversal( assetDocValue, 'files', 'proxy', '2560', 'relativePath' ) ~= nil
					and derefUniversal( assetDocValue, 'files', 'xmp_develop', 'relativePath' ) ~= nil
			
			end
			
		end ),
		true
	)

end

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

function WFCatSpacePurgeUtilsTest.rxTestPurgeSyncedVersionsForSpace( rxTest )

	rxTest:setTimeLimit( 10 )

	local wfCatalog = createFakeWFCatalog( rxTest )
	
	local spaceId = KSIdGenerator.uuidInLowercaseHex()
	local ownerId = KSIdGenerator.uuidInLowercaseHex()
	local spaceUserId = KSIdGenerator.uuidInLowercaseHex()
	
	local spaceDoc = {
		_id = spaceId,
		type = 'space',
		subtype = 'shared',
		download = false,
		private = false,
		location = false,
		metadata = false,
		_serverProvidedMetadata = {
			owner = {
				id = ownerId
			},
			this_space_user = {
				id = spaceUserId
			}
		}
	}
	
	rxTest:waitFor( wfCatalog:docStore():setDocValue( spaceDoc ) )
	
	-- Add an space_user to the space
	
	local spaceUserDoc = {
		_id = spaceUserId,
		type = 'space_user',
		space = { id = spaceId },
		user = { id = KSIdGenerator.uuidInLowercaseHex() },
		role = 'editor'
	}
	
	rxTest:waitFor( wfCatalog:docStore():setDocValue( spaceUserDoc ) )
	
	-- Create asset
	
	local assetId = KSIdGenerator.uuidInLowercaseHex()
	
	local assetDocValue, _ = WFCatAssetTestUtils.createAssetDocument( rxTest, wfCatalog, assetId )
	assetDocValue._spaceId = spaceId
	
	rxTest:waitFor( wfCatalog:docStore():setDocValue( assetDocValue ) )
	
	-- Create a fully synced Version
	
	local versionName = "Foo"
	
	local versionId = rxTest:getFirstValue( WFCatVersions.createVersionForAsset( wfCatalog, assetId, false, versionName ) )
		
	local versionXmpDevelopSettingsFilePath = rxTest:getFirstValue( wfCatalog:docStore():docValue( versionId )
		
			:map( function( versionDocValue )
			
				local path = derefOpt( versionDocValue, '_localOnly', 'files', 'xmp_develop', 'path' )
				
				if WFPlatformInfo.isMobile() then
					path = LrmOzPurgeAgentUtils.absolutePath( wfCatalog:ozCatalogId(), path )
				end
				
				return path
			
			end ) )
	
	local overlay = {
		_id = versionId
	}
	
	local links = {
		['/rels/xmp/develop'] = {
			href = 'foo'
		}
	}
	
	KSTableUtils.setNested( overlay, links, '_serverProvidedMetadata', 'links' )
	
	rxTest:waitFor( wfCatalog:docStore():applyOverlay( overlay ) )
	
	rxTest:observe( wfCatalog:indexStore():query {
			sql = [[SELECT docId FROM versions WHERE spaceId = ?]],
			spaceId
		} )
		:expectDataWithinTime( 2, {{ versionId }} )
		:dispose()
	
	-- check if xmp_develop file exists
	
	rxTest:expectEqual( 'file', WFFileUtils.exists( versionXmpDevelopSettingsFilePath ) )
	
	-- purge versions for space
	
	rxTest:waitFor( WFCatSpacePurgeUtils.DEBUG_purgeVersionsForSpace( wfCatalog, spaceId, true ) )
	
	-- check if xmp_develop file is purged and doc is updated
	-- xmp_develop file won't be purged on desktop, it's handled by PixelProviderFileCachePurgeWorker
	
	if not WFPlatformInfo.isDesktop then
		
		rxTest:expectEqual( false, WFFileUtils.exists( versionXmpDevelopSettingsFilePath ) )
	
	end
	
	rxTest:expectSingleValue( wfCatalog:docStore():docValue( versionId )
		:map( function( versionDocValue )
			
			return derefOpt( versionDocValue, '_localOnly', 'files', 'xmp_develop', 'path' ) == nil

		end ),
		true
	)
	
end

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

function WFCatSpacePurgeUtilsTest.rxTestDontPurgeUnsyncedVersionsForSpace( rxTest )

	rxTest:setTimeLimit( 100 )

	local wfCatalog = createFakeWFCatalog( rxTest )
	
	local spaceId = KSIdGenerator.uuidInLowercaseHex()
	local ownerId = KSIdGenerator.uuidInLowercaseHex()
	local spaceUserId = KSIdGenerator.uuidInLowercaseHex()
	
	local spaceDoc = {
		_id = spaceId,
		type = 'space',
		subtype = 'shared',
		download = false,
		private = false,
		location = false,
		metadata = false,
		_serverProvidedMetadata = {
			owner = {
				id = ownerId
			},
			this_space_user = {
				id = spaceUserId
			}
		}
	}
	
	rxTest:waitFor( wfCatalog:docStore():setDocValue( spaceDoc ) )
	
	-- Add an space_user to the space
	
	local spaceUserDoc = {
		_id = spaceUserId,
		type = 'space_user',
		space = { id = spaceId },
		user = { id = KSIdGenerator.uuidInLowercaseHex() },
		role = 'editor'
	}
	
	rxTest:waitFor( wfCatalog:docStore():setDocValue( spaceUserDoc ) )
	
	-- Create asset
	
	local assetId = KSIdGenerator.uuidInLowercaseHex()
	
	local assetDocValue, _ = WFCatAssetTestUtils.createAssetDocument( rxTest, wfCatalog, assetId )
	assetDocValue._spaceId = spaceId
	
	rxTest:waitFor( wfCatalog:docStore():setDocValue( assetDocValue ) )
	
	-- Create an unsynced Version document.
	
	local versionName = "Foo"
	
	local versionId = rxTest:getFirstValue( WFCatVersions.createVersionForAsset( wfCatalog, assetId, false, versionName ) )
		
	local versionXmpDevelopSettingsFilePath = rxTest:getFirstValue( wfCatalog:docStore():docValue( versionId )
		
			:map( function( versionDocValue )
			
				local path = derefOpt( versionDocValue, '_localOnly', 'files', 'xmp_develop', 'path' )
				
				if WFPlatformInfo.isMobile() then
					path = LrmOzPurgeAgentUtils.absolutePath( wfCatalog:ozCatalogId(), path )
				end
				
				return path
			
			end ) )
	
	rxTest:observe( wfCatalog:indexStore():query{
			sql = [[SELECT docId FROM versions WHERE spaceId = ?]],
			spaceId
		} )
		:expectDataWithinTime( 2, {{ versionId }} )
		:dispose()
	
	-- check if xmp_develop file exists
	
	rxTest:expectEqual( 'file', WFFileUtils.exists( versionXmpDevelopSettingsFilePath ) )
	
	-- purge versions for space
	
	rxTest:waitFor( WFCatSpacePurgeUtils.DEBUG_purgeVersionsForSpace( wfCatalog, spaceId, true ) )
	
	-- Make sure the unsynced version was *not* purged
	
	rxTest:expectEqual( 'file', WFFileUtils.exists( versionXmpDevelopSettingsFilePath ) )

	rxTest:expectSingleValue( wfCatalog:docStore():docValue( versionId )
		:map( function( versionDocValue )
			
			local path = derefOpt( versionDocValue, '_localOnly', 'files', 'xmp_develop', 'path' )
				
			if WFPlatformInfo.isMobile() then
				path = LrmOzPurgeAgentUtils.absolutePath( wfCatalog:ozCatalogId(), path )
			end
			
			return path
			
		end ),
		versionXmpDevelopSettingsFilePath
	)
	
end 

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

return WFRxTestCase.wrapSuite( WFCatSpacePurgeUtilsTest )
