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

NmbAlbumsTest.lua

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

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

NOTICE: All information contained herein is, and remains 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 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 Systems Incorporated.

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

local Rx = require 'Rx'

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

	-- WF.core.utils
local KSDate = require 'KSDate'
local KSIdGenerator = require 'KSIdGenerator'
local KSTableUtils = require 'KSTableUtils'
local WFArguments = require 'WFArguments'
local _ = require 'WFArguments_uuid'
local WFCatIdUtils = require 'WFCatIdUtils'
local WFPlatformInfo = require 'WFPlatformInfo'

local NmbAlbums = require 'NmbAlbums'
local WFCatMockCatalog = require 'WFCatMockCatalog'
local WFCatTestSession = require 'WFCatTestSession'

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

local check = assert( WFArguments.check )

local createFakeWFCatalog = WFCatMockCatalog.createFakeWFCatalog


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

local NmbAlbumsTest = {}

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

local function getSubmodelObservableFromModel( model, submodel, ... )
	
	return model.models[ submodel ]( model, ... ).value

end

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

local function getAlbumListCacheObservableFromModel( model )

	return model._wfCatalog
			:take( 1 )
			:flatMapLatest( 
				function( _, cache ) 
					return cache:getAlbumsFromCache()
				end )
	
end

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

local function makeModelAdderOfAlbum( rxTest, model )

	local counter = 9

	return function( parentId )

		local docId
		local albumName = string.format( "Album %d", counter )

		rxTest:expectOnlyCompleted(

			getSubmodelObservableFromModel( model, 'createAlbum', albumName, parentId )
				:tap( function( localAlbumId, globalAlbumId )
					check( 'number', 'uuid' )
					docId = globalAlbumId
				end )
				:takeLast( 0 )
		)

		counter = counter - 1

		return docId

	end

end

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

local function makeModelAdderOfFolder( rxTest, model )

	local counter = 9

	return function( parentId )

		local docId
		local folderName = string.format( "Folder %d", counter )

		rxTest:expectOnlyCompleted(

			getSubmodelObservableFromModel( model, 'createFolder', folderName, parentId )
				:tap( function( localFolderId, globalFolderId )
					check( 'number', 'uuid' )
					docId = globalFolderId
				end )
				:takeLast( 0 )
		)

		counter = counter - 1

		return docId

	end

end

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

local function makeModelAdderOfProject( rxTest, model, serviceId  )

	local counter = 9

	return function( )

		local projectAlbumId
		local albumName = string.format( "Project %d", counter )

		rxTest:expectOnlyCompleted(

			getSubmodelObservableFromModel( model, 'createConnectionFromPhotos', serviceId, {}, albumName )
				:tap( function( connectedAlbumInfo )
					check( 'table' )
					projectAlbumId = connectedAlbumInfo and connectedAlbumInfo.albumId
				end )
				:takeLast( 0 )
		)

		counter = counter - 1

		return projectAlbumId	
	end
end

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

local function sanitizeAndSortAlbumsList( albums )
	
	albums = albums or {}
	
	albums = KSTableUtils.deepCopy( albums )
	
	local now = KSDate.timeInIso8601Format()
	
	for _, album in ipairs( albums ) do
	
		if type( album.fullDocId ) == 'string' and #album.fullDocId == 32 then
			album.fullDocId = 'uuid'
		end
		
		album.isMarkedForOffline = nil
		album.syncStatus = nil
		
		if KSDate.differenceInSeconds( album.createdTimestamp, now ) < 100 then
			album.createdTimestamp = 'recently'
		end

		if KSDate.differenceInSeconds( album.updateTimestamp, now ) < 100 then
			album.updateTimestamp = 'recently'
		end
	end
	
	table.sort( albums, function( a, b )
			return a.id < b.id
		end )
	return albums
end

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

function NmbAlbumsTest.rxTestCannotReparentOntoSelfWithCache( rxTest )

	rxTest:setTimeLimit( 60 )
	
	WFCatIdUtils.debug_clearCaches()
	
	local wfCatalog = createFakeWFCatalog( rxTest )
	
	local model = NmbAlbums.makeAlbumsModel( Rx.Observable.just( wfCatalog ) )
	
	local addAlbumFn = makeModelAdderOfAlbum( rxTest, model )

	addAlbumFn()
	rxTest:expectOnlyError( getSubmodelObservableFromModel( model, 'reparentAlbum', 1, 1 ), 'InvalidParent' )
	
end

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

function NmbAlbumsTest.rxTestAlbumHierarchyWithCache( rxTest )
	
	rxTest:setTimeLimit( 60 )
	
	WFCatIdUtils.debug_clearCaches()
	
	local wfCatalog = createFakeWFCatalog( rxTest )
	
	local model = NmbAlbums.makeAlbumsModel( Rx.Observable.just( wfCatalog ) )
 
	local addFolderFn = makeModelAdderOfFolder( rxTest, model )
	local addAlbumFn = makeModelAdderOfAlbum( rxTest, model )
	
	-- create a folder
	addFolderFn()
	
	local albumsList = rxTest:observe( 
		getAlbumListCacheObservableFromModel( model )
			:map( sanitizeAndSortAlbumsList ) )
	
	albumsList:expectDataWithinTime( 3, {
			{
				id = 1,
				name = "Folder 9",
				subtype = "collection_set",
				hidden = false,
				hasDisplayFilters = 0,
				fullDocId = "uuid",
				createdTimestamp = "recently",
				updateTimestamp = "recently",
			} } )
	
	-- create a folder in a folder
	addFolderFn( 1 )
	
	local folderWithNestedFolder =  {
			{
				id = 1,
				name = "Folder 9",
				subtype = "collection_set",
				hidden = false,
				hasDisplayFilters = 0,
				fullDocId = "uuid",
				createdTimestamp = "recently",
				updateTimestamp = "recently",
			},
			{
				id = 2,
				parentId = 1,
				name = "Folder 8",
				subtype = "collection_set",
				hidden = false,
				hasDisplayFilters = 0,
				fullDocId = "uuid",
				createdTimestamp = "recently",
				updateTimestamp = "recently",
			},
		}
		
	albumsList:expectDataWithinTime( 3, folderWithNestedFolder )
		
	-- create a loop of folders (failure)
	rxTest:expectOnlyError( getSubmodelObservableFromModel( model, 'reparentAlbum', 1, 2 ), "CycleDetected" )
	
	-- put an album in a folder (ok )
	addAlbumFn( 1 )
	addAlbumFn( 2 )
	
	local foldersWithNestedAlbums = { 
		{
			id = 1,
			name = "Folder 9",
			subtype = "collection_set",
			hidden = false,
			hasDisplayFilters = 0,
			fullDocId = "uuid",
			createdTimestamp = "recently",
			updateTimestamp = "recently",
		},
		{
			id = 2,
			name = "Folder 8",
			parentId = 1,
			subtype = "collection_set",
			hidden = false,
			hasDisplayFilters = 0,
			fullDocId = "uuid",
			createdTimestamp = "recently",
			updateTimestamp = "recently",
		},
		{
			id = 3,
			name = "Album 9",
			parentId = 1,
			subtype = "collection",
			hidden = false,
			hasDisplayFilters = 0,
			fullDocId = "uuid",
			createdTimestamp = "recently",
			updateTimestamp = "recently",
		},
		{
			id = 4,
			name = "Album 8",
			parentId = 2,
			subtype = "collection",
			hidden = false,
			hasDisplayFilters = 0,
			fullDocId = "uuid",
			createdTimestamp = "recently",
			updateTimestamp = "recently",
		},
	}
	
	albumsList:expectDataWithinTime( 3, foldersWithNestedAlbums )
	
	-- create a folder in an album (failure)
	rxTest:expectOnlyError( getSubmodelObservableFromModel( model, 'createFolder', 'Folder 10', 3 ), "InvalidParent" )
	
	albumsList:expectDataWithinTime( 3, foldersWithNestedAlbums )
	
	-- move a folder into an album (failure)
	rxTest:expectOnlyError( getSubmodelObservableFromModel( model, 'reparentAlbum', 4, 3 ), "InvalidParent" )
	
	albumsList:expectDataWithinTime( 3, foldersWithNestedAlbums )

end

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

function NmbAlbumsTest.rxTestDeleteAlbumsAndFoldersWithCache( rxTest )
	
	rxTest:setTimeLimit( 60 )
	
	WFCatIdUtils.debug_clearCaches()
	
	local wfCatalog = createFakeWFCatalog( rxTest )
	
	local model = NmbAlbums.makeAlbumsModel( Rx.Observable.just( wfCatalog ) )
 
	local addFolderFn = makeModelAdderOfFolder( rxTest, model )
	local addAlbumFn = makeModelAdderOfAlbum( rxTest, model )

	addFolderFn() -- 1
	addAlbumFn() -- 2
	
	local albumsList = rxTest:observe( 
		getAlbumListCacheObservableFromModel( model )
			:map( sanitizeAndSortAlbumsList ) )
	
	albumsList:expectDataWithinTime( 5, {
			{
				id = 1,
				name = "Folder 9",
				subtype = "collection_set",
				hidden = false,
				hasDisplayFilters = 0,
				fullDocId = "uuid",
				createdTimestamp = "recently",
				updateTimestamp = "recently",
			},
			{
				id = 2,
				name = "Album 9",
				subtype = "collection",
				hidden = false,
				hasDisplayFilters = 0,
				fullDocId = "uuid",
				createdTimestamp = "recently",
				updateTimestamp = "recently",
			},
		} )
	
	-- delete folder
	rxTest:expectOnlyCompleted( getSubmodelObservableFromModel( model, 'deleteAlbum', 1 ) )
	
	albumsList:expectDataWithinTime( 5, {
			{
				id = 2,
				name = "Album 9",
				subtype = "collection",
				hidden = false,
				hasDisplayFilters = 0,
				fullDocId = "uuid",
				createdTimestamp = "recently",
				updateTimestamp = "recently",
			},
		} )
	
	-- delete album
	rxTest:expectOnlyCompleted( getSubmodelObservableFromModel( model, 'deleteAlbum', 2 ) )
	
	albumsList:expectDataWithinTime( 5, { } )
	
	-- create nested structure
	addFolderFn() -- 3
	addFolderFn() -- 4
	addFolderFn( 4 ) -- 4 -> 5
	addAlbumFn( 3 ) -- 3 -> 6
	addAlbumFn( 5 ) -- 4 -> 5 -> 7
	
	albumsList:expectDataWithinTime( 5, {
		{
			id = 3,
			name = "Folder 8",
			subtype = "collection_set",
			hidden = false,
			hasDisplayFilters = 0,
			fullDocId = "uuid",
			createdTimestamp = "recently",
			updateTimestamp = "recently",
		},
		{
			id = 4,
			name = "Folder 7",
			subtype = "collection_set",
			hidden = false,
			hasDisplayFilters = 0,
			fullDocId = "uuid",
			createdTimestamp = "recently",
			updateTimestamp = "recently",
		},
		{
			id = 5,
			name = "Folder 6",
			parentId = 4,
			subtype = "collection_set",
			hidden = false,
			hasDisplayFilters = 0,
			fullDocId = "uuid",
			createdTimestamp = "recently",
			updateTimestamp = "recently",
		},
		{
			id = 6,
			name = "Album 8",
			parentId = 3,
			subtype = "collection",
			hidden = false,
			hasDisplayFilters = 0,
			fullDocId = "uuid",
			createdTimestamp = "recently",
			updateTimestamp = "recently",
		},
		{
			id = 7,
			name = "Album 7",
			parentId = 5,
			subtype = "collection",
			hidden = false,
			hasDisplayFilters = 0,
			fullDocId = "uuid",
			createdTimestamp = "recently",
			updateTimestamp = "recently",
		},
		} )
	
	-- delete nested album (should leave containing folder)
	rxTest:expectOnlyCompleted( getSubmodelObservableFromModel( model, 'deleteAlbum', 6 ) )
	
	albumsList:expectDataWithinTime( 5, {
		{
			id = 3,
			name = "Folder 8",
			subtype = "collection_set",
			hidden = false,
			hasDisplayFilters = 0,
			fullDocId = "uuid",
			createdTimestamp = "recently",
			updateTimestamp = "recently",
		},
		{
			id = 4,
			name = "Folder 7",
			subtype = "collection_set",
			hidden = false,
			hasDisplayFilters = 0,
			fullDocId = "uuid",
			createdTimestamp = "recently",
			updateTimestamp = "recently",
		},
		{
			id = 5,
			name = "Folder 6",
			parentId = 4,
			subtype = "collection_set",
			hidden = false,
			hasDisplayFilters = 0,
			fullDocId = "uuid",
			createdTimestamp = "recently",
			updateTimestamp = "recently",
		},
		{
			id = 7,
			name = "Album 7",
			parentId = 5,
			subtype = "collection",
			hidden = false,
			hasDisplayFilters = 0,
			fullDocId = "uuid",
			createdTimestamp = "recently",
			updateTimestamp = "recently",
		},
		} )
	
	-- delete top level album (children should go too)
	rxTest:expectOnlyCompleted( getSubmodelObservableFromModel( model, 'deleteAlbum', 4 ) )
	
	albumsList:expectDataWithinTime( 5, {
			{
				id = 3,
				name = "Folder 8",
				subtype = "collection_set",
				hidden = false,
				hasDisplayFilters = 0,
				fullDocId = "uuid",
				createdTimestamp = "recently",
				updateTimestamp = "recently",
			}
		} )
	
	-- SPAM [matthewj 2017-01-20]: do we need to check that all assets for an album are also deleted?
end

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

function NmbAlbumsTest.rxTestBasicFoldersWithCache( rxTest )
	
	rxTest:setTimeLimit( 60 )
	
	WFCatIdUtils.debug_clearCaches()
	
	local wfCatalog = createFakeWFCatalog( rxTest )
	
	local model = NmbAlbums.makeAlbumsModel( Rx.Observable.just( wfCatalog ) )
 
	local addFolderFn = makeModelAdderOfFolder( rxTest, model )

	addFolderFn()
	addFolderFn()
	addFolderFn()

	local foldersData = rxTest:observe(
		model._wfCatalog
			:take( 1 )
			:flatMapLatest( 
				function( _, cache ) 
					return cache:getAlbumsFromCache():map( sanitizeAndSortAlbumsList ) 
				end ) )

	local expectedFoldersData = {
		{
			id = 1,
			name = "Folder 9",
			subtype = "collection_set",
			hidden = false,
			hasDisplayFilters = 0,
			fullDocId = "uuid",
			createdTimestamp = "recently",
			updateTimestamp = "recently",
		},
		{
			id = 2,
			name = "Folder 8",
			subtype = "collection_set",
			hidden = false,
			hasDisplayFilters = 0,
			fullDocId = "uuid",
			createdTimestamp = "recently",
			updateTimestamp = "recently",
		},
		{
			id = 3,
			name = "Folder 7",
			subtype = "collection_set",
			hidden = false,
			hasDisplayFilters = 0,
			fullDocId = "uuid",
			createdTimestamp = "recently",
			updateTimestamp = "recently",
		},
	}

	foldersData:expectDataWithinTime( 30, expectedFoldersData )

	rxTest:expectOnlyCompleted( getSubmodelObservableFromModel( model, 'renameAlbum', 3, "Renamed Folder" ) )
	expectedFoldersData[ 3 ].name = 'Renamed Folder'
	
	foldersData:expectDataWithinTime( 30, expectedFoldersData )

	rxTest:expectOnlyCompleted( getSubmodelObservableFromModel( model, 'deleteAlbum', 1 ) )
	table.remove( expectedFoldersData, 1 )
	
	foldersData:expectDataWithinTime( 30, expectedFoldersData )

	rxTest:expectOnlyCompleted( getSubmodelObservableFromModel( model, 'deleteAlbum', 2 ) )
	
	
end

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

function NmbAlbumsTest.rxTestBasicAlbumsWithCache( rxTest )

	rxTest:setTimeLimit( 60 )
	
	WFCatIdUtils.debug_clearCaches()
	
	local wfCatalog = createFakeWFCatalog( rxTest )

	local model = NmbAlbums.makeAlbumsModel( Rx.Observable.just( wfCatalog ) )
 
	local addAlbumFn = makeModelAdderOfAlbum( rxTest, model )

	addAlbumFn()
	addAlbumFn()
	addAlbumFn()

	local albumsData = rxTest:observe( 
		model._wfCatalog
			:take( 1 )
			:flatMapLatest( 
				function( _, cache ) 
					return cache:getAlbumsFromCache():map( sanitizeAndSortAlbumsList ) 
				end ) )

	local expectedAlbumsData = {
		{
			id = 1,
			name = "Album 9",
			subtype = "collection",
			hidden = false,
			hasDisplayFilters = 0,
			fullDocId = "uuid",
			createdTimestamp = "recently",
			updateTimestamp = "recently",
		},
		{
			id = 2,
			name = "Album 8",
			subtype = "collection",
			hidden = false,
			hasDisplayFilters = 0,
			fullDocId = "uuid",
			createdTimestamp = "recently",
			updateTimestamp = "recently",
		},
		{
			id = 3,
			name = "Album 7",
			subtype = "collection",
			hidden = false,
			hasDisplayFilters = 0,
			fullDocId = "uuid",
			createdTimestamp = "recently",
			updateTimestamp = "recently",
		},
	}

	albumsData:expectDataWithinTime( 30, expectedAlbumsData )

	rxTest:expectOnlyCompleted( getSubmodelObservableFromModel( model, 'renameAlbum', 3, "Renamed Album" ) )
	expectedAlbumsData[ 3 ].name = 'Renamed Album'
	
	albumsData:expectDataWithinTime( 30, expectedAlbumsData )

	rxTest:expectOnlyCompleted( getSubmodelObservableFromModel( model, 'deleteAlbum', 1 ) )
	table.remove( expectedAlbumsData, 1 )
	
	albumsData:expectDataWithinTime( 30, expectedAlbumsData )

	rxTest:expectOnlyCompleted( getSubmodelObservableFromModel( model, 'deleteAlbum', 2 ) )

end

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

function NmbAlbumsTest.rxTestAdhocAlbumsSynchronouslyWithCache_testNightly( rxTest )

	rxTest:setTimeLimit( 60 )
	
	WFCatIdUtils.debug_clearCaches()
	
	local wfCatalog

	local catalogTestSession = WFCatTestSession( rxTest, 'NmbCatalog' )
	
	rxTest:waitFor( catalogTestSession:catalog()
		:map( function( _catalog )
			check( 'WFCatalog' )
			wfCatalog = _catalog
			return _catalog
		end ) )
	
	rxTest:finally( function()
		wfCatalog:indexStore():close()
	end )

	local model = NmbAlbums.makeAlbumsModel( Rx.Observable.just( wfCatalog ) )
 
	local albumId
	local albumName = "Album adhoc"
	local successfullyCreatedWithOz = false

	rxTest:expectOnlyCompleted(

		getSubmodelObservableFromModel( model, 'createAdhocAlbumSynchronously', albumName )
			:tap( function( values )
				check( 'table' )

				local globalAlbumId = values.albumDocId
				local didCreateWithOz = values.didCreateWithOz

				albumId = globalAlbumId
				successfullyCreatedWithOz = didCreateWithOz
			end )
			:takeLast( 0 )
	)

	rxTest:expectEqual( successfullyCreatedWithOz, true )

	local albumsData = rxTest:observe( 
		model._wfCatalog
			:take( 1 )
			:flatMapLatest( 
				function( _, cache ) 
					return cache:getAdhocAlbumsFromCache():map( sanitizeAndSortAlbumsList )
				end ) )

	local expectedAlbumsData = {
		{
			id = 1,
			name = "Album adhoc",
			subtype = "collection",
			hidden = true,
			hasDisplayFilters = 0,
			fullDocId = "uuid",
			createdTimestamp = "recently",
			updateTimestamp = "recently",
		}
	}

	albumsData:expectDataWithinTime( 30, expectedAlbumsData )

end

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

function NmbAlbumsTest.rxTestSetProjectState( rxTest )

	rxTest:setTimeLimit( 10 )
	
	WFCatIdUtils.debug_clearCaches()
	
	local wfCatalog = createFakeWFCatalog( rxTest )
	
	local model = NmbAlbums.makeAlbumsModel( Rx.Observable.just( wfCatalog ) )
		
	local addProjectFn = makeModelAdderOfProject( rxTest, model , "FakeService" )

	local albumId = addProjectFn() -- create a project

	rxTest:expectSingleValue( getSubmodelObservableFromModel( model, 'getConnectionAttributes', albumId )
		:map( function( result )
		    result.userUpdated = nil
		    result.userCreated = nil
		   return result
		end ),	
		{
			serviceId = "FakeService",
		})
		
	rxTest:expectOnlyCompleted( getSubmodelObservableFromModel( model, 'setProjectState', albumId, "active" ) )	
	
	rxTest:expectSingleValue( getSubmodelObservableFromModel( model, 'getConnectionAttributes', albumId )
		:map( function( result )
		    result.userUpdated = nil
		    result.userCreated = nil
		   return result
		end ),	
		{	
			projectState = "active",
			serviceId = "FakeService",
		} )
		
	rxTest:expectOnlyCompleted( getSubmodelObservableFromModel( model, 'setProjectState', albumId, "completed" ) )	
	
	rxTest:expectSingleValue( getSubmodelObservableFromModel( model, 'getConnectionAttributes', albumId )
		:map( function( result )
		    result.userUpdated = nil
		    result.userCreated = nil
		   return result
		end ),
		{	
			projectState = "completed",
			serviceId = "FakeService",
		} )

end

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

local function sortById( results )
	
	table.sort( results, function( a, b ) return a.id < b.id end )
	
	return results
end
--------------------------------------------------------------------------------

function NmbAlbumsTest.rxTestGetAlbumAssetsAndSubtype( rxTest )
	
	rxTest:setTimeLimit( 5 )
	
	WFCatIdUtils.debug_clearCaches()
	
	local wfCatalog = createFakeWFCatalog( rxTest )

	local model = NmbAlbums.makeAlbumsModel( Rx.Observable.just( wfCatalog ) )
 
	local addAlbumFn = makeModelAdderOfAlbum( rxTest, model )

	addAlbumFn()

	local albumsData = rxTest:observe( 
		model._wfCatalog
			:take( 1 )
			:flatMapLatest( 
				function( _, cache ) 
					return cache:getAlbumsFromCache():map( sanitizeAndSortAlbumsList ) 
				end ) )

	local expectedAlbumsData = {
		{
			id = 1,
			name = "Album 9",
			subtype = "collection",
			hidden = false,
			hasDisplayFilters = 0,
			fullDocId = "uuid",
			createdTimestamp = "recently",
			updateTimestamp = "recently",
		},
	}

	albumsData:expectDataWithinTime( 30, expectedAlbumsData )
	
	-- album should be empty, so no ids and subtypes
	rxTest:expectSingleValue( getSubmodelObservableFromModel( model, 'getAlbumAssetsAndSubtype', 1 ), {} )
	
	local assetDoc1 = WFOzTestUtils.v2.makeBaseValidAssetDocument( KSIdGenerator.uuidInLowercaseHex() )
	local assetDoc2 =  WFOzTestUtils.v2.makeBaseValidAssetDocument( KSIdGenerator.uuidInLowercaseHex() )
	assetDoc2.subtype = 'video'
	rxTest:waitFor( wfCatalog:docStore():bulkSetDocValue( { assetDoc1, assetDoc2 } ) )
	
	rxTest:waitFor( getSubmodelObservableFromModel( model, 'addAssetsToAlbum', 1, { assetDoc1._id, assetDoc2._id } ) )
		
	local sortedResults = sortById( { {
			id = assetDoc1._id,
			subtype = 'image',
		},
		{ 
			id = assetDoc2._id,
			subtype = 'video',
		} } )
		
	rxTest:expectSingleValue( getSubmodelObservableFromModel( model, 'getAlbumAssetsAndSubtype', 1 ):map( sortById ), sortedResults )
	
	local assetDoc3 = {
		_id = KSIdGenerator.uuidInLowercaseHex(), 
		type = 'asset',
		subtype = 'other',
		field1 = 'value1',
		field2 = 'value2',
	}
	
	rxTest:waitFor( wfCatalog:docStore():setDocValue( assetDoc3 ) )
	rxTest:waitFor( getSubmodelObservableFromModel( model, 'addAssetsToAlbum', 1, { assetDoc3._id } ) )
	
	sortedResults = sortById( { {
			id = assetDoc1._id,
			subtype = 'image',
		},
		{ 
			id = assetDoc2._id,
			subtype = 'video',
		},
		{ 
			id = assetDoc3._id,
		} } )
		
	rxTest:expectSingleValue( getSubmodelObservableFromModel( model, 'getAlbumAssetsAndSubtype', 1 ):map( sortById ), sortedResults )
	
end

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

local i = 0

local function createFeedbackUser( userId )

	i = i + 1

	local name = string.format( 'Full Name %s', tostring( i ) )

	return {
		_id = userId,
		type = 'feedbackuser',
		
		_serverProvidedMetadata = {
			full_name = name,
			email = string.format( 'person_%s@gmail.com', tostring( i ) ),
			links = {
				[ '/rels/avatars/medium' ] = {
					href = '/v2/dummy_avatar_medium',
				},
				[ '/rels/avatars/large' ] = {
					href = '/v2/dummy_avatar_large',
				},
			},
		},
	}, name
	
end

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

if WFPlatformInfo.isDesktop then

function NmbAlbumsTest.rxTestSharedWithYouAlbumsList( rxTest )

	rxTest:setTimeLimit( 60 )
	
	WFCatIdUtils.debug_clearCaches()
	
	local wfCatalog = createFakeWFCatalog( rxTest )

	local model = NmbAlbums.makeAlbumsModel( Rx.Observable.just( wfCatalog ) )
 
	local addAlbumFn = makeModelAdderOfAlbum( rxTest, model )

	local albumId1 = addAlbumFn()
	local albumId2 = addAlbumFn()
	local albumId3 = addAlbumFn()
	
	local albumIds = {
		albumId1,
		albumId2,
		albumId3
	}
	
	local ownerId = KSIdGenerator.uuidInLowercaseHex()
	
	-- Create the space.
	
	local spaceId = KSIdGenerator.uuidInLowercaseHex()
	local thisSpaceUser = KSIdGenerator.uuidInLowercaseHex()
	
	local space = {
		_id = spaceId,
		type = 'space',
		subtype = 'shared',
		download = true,
		metadata = false,
		location = true,
		comments_disabled = false,
		favorites_disabled = true,
		_serverProvidedMetadata = {
			owner = {
				id = ownerId
			},
			this_space_user = {
				id = thisSpaceUser,
			},
		}
	}
	
	rxTest:expectSingleValue( wfCatalog:docStore():setDocValue( space ), ':ignore:' )
	
	-- Create the space_user
	
	local spaceUserCreated = "2020-03-04T15:39:24.281646Z"
	
	local space_user = {
		type = 'space_user',
		_id = thisSpaceUser,
		role = "viewer",
		user = {
			id = KSIdGenerator.uuidInLowercaseHex(),
		},
		status = "accepted",
		space = {
			id = spaceId,
		},
		userCreated = spaceUserCreated,
	}
	
	rxTest:expectSingleValue( wfCatalog:docStore():setDocValue( space_user ), ':ignore:' )

	
	-- Create the owner feedback user
	
	local feedbackuserDoc, ownerName = createFeedbackUser( ownerId )
	
	rxTest:expectSingleValue( wfCatalog:docStore():setDocValue( feedbackuserDoc ), ':ignore:' )
	
	-- Add albums to the space.
	
	local overlays = {}

	for i, albumId in ipairs( albumIds ) do
	
		overlays[ #overlays + 1 ] = {
			_id = albumId,
			_spaceId = spaceId,
			name = "Foo",
		}
		
		overlays[ #overlays + 1 ] = {
		
			_id = KSIdGenerator.uuidInLowercaseHex(),
			type = 'space_album',
			space = {
				id = spaceId,
			},
			album = {
				id = albumId,
			}
		
		}
		
	end

	rxTest:expectSingleValue( wfCatalog:docStore():bulkApplyOverlay( overlays ), ':ignore:' )
	
	local spaceObserver = rxTest:observe( ( wfCatalog:indexStore():query {
			sql = [[SELECT * from space WHERE isDeleted == 0]],
		} ) )
	
	spaceObserver:expectDataWithinTime( 5, {
		{
			spaceId,
			[4] = 0,
			[5] = 1,
			[6] = 0,
			[7] = 0,
			[8] = 1,
			[9] = 1,
			[10] = 0,
			[11] = ownerId,
			[12] = 0,
			[13] = 0,
			[14] = thisSpaceUser,
			[16] = 0,
			[17] = nil,
			[18] = nil,
			[19] = 0,
			[20] = 0,
		} } )
	
	local observer = rxTest:observe( getSubmodelObservableFromModel( model, 'sharedWithYouAlbumsList' )
		:map( function( albumsContainer )
			albumsContainer.albums = sanitizeAndSortAlbumsList( albumsContainer.albums )
			return albumsContainer
		end ) )
	
	observer:expectDataWithinTime( 5, 
		{
			albums = {
				{
					fullDocId = 'uuid',
					hasDisplayFilters = 0,
					hidden = false,
					id = 1,
					joinedTimestamp = spaceUserCreated,
					name = "Foo",
					ownerInfo = {
						id = ownerId,
						name = ownerName,
						outOfQuota = false,
						subscriptionLapsed = false,
					},
					permissions = {
						role = "viewer",
					},
					shareSettings = {
						allowComments = true,
						allowDownloads = true,
						allowFavorites = false,
						showLocation = true,
						showMetadata = false,
					},
					spaceId = spaceId,
					subtype = "collection",
					createdTimestamp = "recently",
					updateTimestamp = "recently",
				},
				{
					fullDocId = 'uuid',
					hasDisplayFilters = 0,
					hidden = false,
					id = 2,
					joinedTimestamp = spaceUserCreated,
					name = "Foo",
					ownerInfo = {
						id = ownerId,
						name = ownerName,
						outOfQuota = false,
						subscriptionLapsed = false,
					},
					permissions = {
						role = "viewer",
					},
					shareSettings = {
						allowComments = true,
						allowDownloads = true,
						allowFavorites = false,
						showLocation = true,
						showMetadata = false,
					},
					spaceId = spaceId,
					subtype = "collection",
					createdTimestamp = "recently",
					updateTimestamp = "recently",
				},
				{
					fullDocId = 'uuid',
					hasDisplayFilters = 0,
					hidden = false,
					id = 3,
					joinedTimestamp = spaceUserCreated,
					name = "Foo",
					ownerInfo = {
						id = ownerId,
						name = ownerName,
						outOfQuota = false,
						subscriptionLapsed = false,
					},
					permissions = {
						role = "viewer",
					},
					shareSettings = {
						allowComments = true,
						allowDownloads = true,
						allowFavorites = false,
						showLocation = true,
						showMetadata = false,
					},
					spaceId = spaceId,
					subtype = "collection",
					createdTimestamp = "recently",
					updateTimestamp = "recently",
				},
			}
		} )

end

end

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

return WFRxTestCase.wrapSuite( 'NmbAlbumsTest', NmbAlbumsTest )
