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

WFCatCollaborationActivityTest.lua

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

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

NOTICE: All information contained herein is, and remain 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 may be covered by U.S. and Foreign
Patents, patents in process, and are protected by trade secret or copyright
law.  Dissemination of this information or reproduction of this material is
strictly forbidden unless prior written permission is obtained from
Adobe Systems Incorporated.

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


local KSIdGenerator = require 'KSIdGenerator'
local WFRxTestCase = require 'WFRxTestCase'
local WFCatAssetTestUtils = require 'WFCatAssetTestUtils'
local WFCatCollaborationActivityTestUtils = require 'WFCatCollaborationActivityTestUtils'
local WFPlatformInfo = require "WFPlatformInfo"
local WFModelsUtils = require 'WFModelsUtils'

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

local kTestDate1 = "2011-11-11T11:11:11.111111Z"
local kTestDate2 = "2020-11-11T11:11:11.111111Z"

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

return function( optSubmodelsByImplementation, maybeExistingTestClass )

	----------------------------------------------------------------------------
	
	local function callFunctionOrSubmodel( rxTest, wfCatalog, fnNamespace, fnName, ... )

		return WFModelsUtils.callFunctionOrSubmodel( rxTest, optSubmodelsByImplementation, wfCatalog, fnNamespace, fnName, ... )

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

	local WFCatCollaborationActivityTest = maybeExistingTestClass or {}

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

	function WFCatCollaborationActivityTest.rxTestGetCommentsForAsset( rxTest )

		rxTest:setTimeLimit( 10 )
		
		local catalog = WFCatCollaborationActivityTestUtils.createFakeWFCatalog( rxTest )
		local docStore = catalog:docStore()
		
		local albumInfo, assetInfo = WFCatCollaborationActivityTestUtils.createSharedAlbumWithAsset( rxTest, catalog )
		
		-- Simulate already added comments
		local currUserId = catalog:ozUserId()
		local commentBody = "comment1"
		local comments = {
			WFCatCollaborationActivityTestUtils.createComment( albumInfo.spaceId, assetInfo.globalId, currUserId, commentBody ),
		}
		
		rxTest:expectOnlyCompleted(
			docStore:bulkSetDocValue( comments )
				:takeLast( 0 ) )
		
		-- Read comment for asset
		local getComments = rxTest:observe( 
				callFunctionOrSubmodel(
					rxTest, catalog,
					'WFCatCollaborationActivity', 'getCommentsForAsset', catalog, albumInfo.localId, assetInfo.localId )
					:map( function( comments )
					
						local simplifiedResults = {}
						
						for _, comment in ipairs( comments ) do
						
							simplifiedResults[ #simplifiedResults + 1 ] = {
								body = comment.body,
								author = comment.author,
								updated = comment.updated,
								created = comment.created,
							}
							
						end
						
						return simplifiedResults
						
					end ) )
		
		getComments:expectDataWithinTime( 3, {
			{
				body = commentBody,
				author = currUserId,
				updated = kTestDate2,
				created = kTestDate1
			}
		} )
		
		getComments:dispose()
		
	end

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

	function WFCatCollaborationActivityTest.rxTestDeleteComment( rxTest )

		rxTest:setTimeLimit( 10 )
		
		local catalog = WFCatCollaborationActivityTestUtils.createFakeWFCatalog( rxTest )
		local docStore = catalog:docStore()
		
		local albumInfo, assetInfo = WFCatCollaborationActivityTestUtils.createSharedAlbumWithAsset( rxTest, catalog )
		
		-- Simulate already added comments
		local currUserId = catalog:ozUserId()
		local commentBody = "comment1"
		local comment = WFCatCollaborationActivityTestUtils.createComment( albumInfo.spaceId, assetInfo.globalId, currUserId, commentBody )
		rxTest:expectSingleValue( docStore:setDocValue( comment ), ':ignore:' )
		
		-- the comment document should exist
		rxTest:expectSingleValue( docStore:docValue( comment._id )
										:map( function( docValue )
											return docValue._deleted == true
										end ), false )
		
		-- delete the comment document
		rxTest:expectOnlyCompleted( 				
				callFunctionOrSubmodel(
					rxTest, catalog,
					'WFCatCollaborationActivity', 'deleteComment', catalog, comment._id ) )
		
		-- the comment document should now deleted
		rxTest:expectSingleValue( docStore:docValue( comment._id )
										:map( function( docValue )
											return docValue._deleted == true
										end ), true )
		
	end

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

	function WFCatCollaborationActivityTest.rxTestAddAndGetComment( rxTest )

		rxTest:setTimeLimit( 10 )
		
		local catalog = WFCatCollaborationActivityTestUtils.createFakeWFCatalog( rxTest )
		local docStore = catalog:docStore()
		
		local albumInfo, assetInfo = WFCatCollaborationActivityTestUtils.createSharedAlbumWithAsset( rxTest, catalog )
		
		-- Simulate already added comments
		local currUserId = catalog:ozUserId()
		local commentBody = "comment1"
		local comment = WFCatCollaborationActivityTestUtils.createComment( albumInfo.spaceId, assetInfo.globalId, currUserId, commentBody )
		rxTest:expectSingleValue( docStore:setDocValue( comment ), ':ignore:' )
		
		-- Read comment for asset
		local getComments = rxTest:observe( 
				callFunctionOrSubmodel(
					rxTest, catalog,
					'WFCatCollaborationActivity', 'getCommentsForAsset', catalog, albumInfo.localId, assetInfo.localId )
					:map( function( comments )
						return comments and #comments or 0
					end ) )
		
		getComments:expectDataWithinTime( 3, 1 )
		
		-- Add comment for asset
		rxTest:expectOnlyCompleted( 				
				callFunctionOrSubmodel(
					rxTest, catalog,
					'WFCatCollaborationActivity', 'addCommentForAsset', catalog, albumInfo.localId, assetInfo.localId, commentBody ) )
		
		getComments:expectDataWithinTime( 3, 2 )
		
		getComments:dispose()
		
	end

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

	function WFCatCollaborationActivityTest.rxTestGetFavoritesForAsset( rxTest )

		rxTest:setTimeLimit( 10 )
		
		local catalog = WFCatCollaborationActivityTestUtils.createFakeWFCatalog( rxTest )
		local docStore = catalog:docStore()
		
		local albumInfo, assetInfo = WFCatCollaborationActivityTestUtils.createSharedAlbumWithAsset( rxTest, catalog )
		
		-- Simulate already added favorite
		local currUserId = catalog:ozUserId()
		local favoriteDoc1 = WFCatCollaborationActivityTestUtils.createFavorite( albumInfo.spaceId, assetInfo.globalId, currUserId )
		rxTest:expectOnlyCompleted(
			docStore:bulkSetDocValue( { favoriteDoc1 } )
				:takeLast( 0 ) )

		-- Read favorites for asset
		local getFavorites = rxTest:observe( 
				callFunctionOrSubmodel(
					rxTest, catalog,
					'WFCatCollaborationActivity', 'getFavoritesForAsset', catalog, albumInfo.localId, assetInfo.localId )
					:map( function( favorites )
						return favorites and #favorites or 0
					end ) )
		
		getFavorites:expectDataWithinTime( 3, 1 )
		
		-- add two more favorite docs
		local favoriteDoc2 = WFCatCollaborationActivityTestUtils.createFavorite( albumInfo.spaceId, assetInfo.globalId, "newUserId1" )
		rxTest:expectOnlyCompleted(
			docStore:bulkSetDocValue( { favoriteDoc2 } )
				:takeLast( 0 ) )
		
		local favoriteDoc3 = WFCatCollaborationActivityTestUtils.createFavorite( albumInfo.spaceId, assetInfo.globalId, "newUserId2" )
		rxTest:expectOnlyCompleted(
			docStore:bulkSetDocValue( { favoriteDoc3 } )
				:takeLast( 0 ) )
		
		getFavorites:expectDataWithinTime( 3, 3 )
		
		getFavorites:dispose()
		
	end

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

	function WFCatCollaborationActivityTest.rxTestRemoveAndGetFavorite( rxTest )

		rxTest:setTimeLimit( 10 )
		
		local catalog = WFCatCollaborationActivityTestUtils.createFakeWFCatalog( rxTest )
		local docStore = catalog:docStore()
		
		local albumInfo, assetInfo = WFCatCollaborationActivityTestUtils.createSharedAlbumWithAsset( rxTest, catalog )
		
		-- Simulate already added favorites
		local currUserId = catalog:ozUserId()
		local favoriteDoc1 = WFCatCollaborationActivityTestUtils.createFavorite( albumInfo.spaceId, assetInfo.globalId, currUserId )
		local favoriteDoc2 = WFCatCollaborationActivityTestUtils.createFavorite( albumInfo.spaceId, assetInfo.globalId, "newUserId" )
		rxTest:expectOnlyCompleted(
			docStore:bulkSetDocValue( { favoriteDoc1, favoriteDoc2 } )
				:takeLast( 0 ) )
		
		-- Read favorites for asset
		local getFavorites = rxTest:observe( 
				callFunctionOrSubmodel(
					rxTest, catalog,
					'WFCatCollaborationActivity', 'getFavoritesForAsset', catalog, albumInfo.localId, assetInfo.localId )
					:map( function( favorites )
						return favorites and #favorites or 0
					end ) )
		
		getFavorites:expectDataWithinTime( 3, 2 )
		
		rxTest:expectOnlyCompleted( 				
				callFunctionOrSubmodel(
					rxTest, catalog,
					'WFCatCollaborationActivity', 'removeFavorite', catalog, albumInfo.localId, assetInfo.localId ) )
		
		getFavorites:expectDataWithinTime( 3, 1 )
		
		getFavorites:dispose()
		
	end

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

	function WFCatCollaborationActivityTest.rxTestAddAndGetFavorite( rxTest )

		rxTest:setTimeLimit( 10 )

		local catalog = WFCatCollaborationActivityTestUtils.createFakeWFCatalog( rxTest )
		local docStore = catalog:docStore()
		
		local albumInfo, assetInfo = WFCatCollaborationActivityTestUtils.createSharedAlbumWithAsset( rxTest, catalog )
		
		-- Simulate already added favorites
		local favoriteDoc1 = WFCatCollaborationActivityTestUtils.createFavorite( albumInfo.spaceId, assetInfo.globalId, "contributor1" )
		local favoriteDoc2 = WFCatCollaborationActivityTestUtils.createFavorite( albumInfo.spaceId, assetInfo.globalId, "contributor2" )
		rxTest:expectOnlyCompleted(
			docStore:bulkSetDocValue( { favoriteDoc1, favoriteDoc2 } )
				:takeLast( 0 ) )
		
		-- Read favorites for asset
		local getFavorites = rxTest:observe( 
				callFunctionOrSubmodel(
					rxTest, catalog,
					'WFCatCollaborationActivity', 'getFavoritesForAsset', catalog, albumInfo.localId, assetInfo.localId )
					:map( function( favorites )
						return favorites and #favorites or 0
					end ) )
		
		getFavorites:expectDataWithinTime( 3, 2 )
		
		rxTest:expectOnlyCompleted( 				
				callFunctionOrSubmodel(
					rxTest, catalog,
					'WFCatCollaborationActivity', 'addFavorite', catalog, albumInfo.localId, assetInfo.localId ) )
		
		getFavorites:expectDataWithinTime( 3, 3 )
		
		getFavorites:dispose()
		
	end

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

	function WFCatCollaborationActivityTest.rxTestRemoveFavoriteFromSharedAsset( rxTest )

		rxTest:setTimeLimit( 10 )
		
		local catalog = WFCatCollaborationActivityTestUtils.createFakeWFCatalog( rxTest, true )
		local docStore = catalog:docStore()
		
		-- Insert a shared-with-you album into the doc store.
		
		local spaceId = KSIdGenerator.uuidInLowercaseHex()
		local albumId = KSIdGenerator.uuidInLowercaseHex()
		
		local albumDoc = {

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

		}
		
		rxTest:waitFor( docStore:setDocValue( albumDoc ) )
		
		-- Insert a space doc into the doc store.
		
		local spaceUserId = KSIdGenerator.uuidInLowercaseHex()
		local feedbackUserId = KSIdGenerator.uuidInLowercaseHex()
		
		local spaceDoc = {
			_id = spaceId,
			type = 'space',
			subtype = 'shared',
			download = false,
			private = false,
			location = false,
			metadata = false,
			_serverProvidedMetadata = {
				this_space_user = {
					id = spaceUserId,
					user = {
						id = feedbackUserId
					}
				}
			}
		}
		
		rxTest:waitFor( docStore:setDocValue( spaceDoc ) )
		
		-- Create the space album doc
		
		local spaceAlbumDoc = {
			type = 'space_album',
			_id = KSIdGenerator.uuidInLowercaseHex(),
			album = {
				id = albumId,
			},
			space = {
				id = spaceId,
			},
		}
		
		rxTest:waitFor( docStore:setDocValue( spaceAlbumDoc ) )
		
		-- Add an asset into the shared album.
		
		local assetId = KSIdGenerator.uuidInLowercaseHex()
		local assetDoc1 = WFCatAssetTestUtils.createAssetDocument( rxTest, catalog, assetId )
		assetDoc1._spaceId = spaceId
		
		rxTest:waitFor( docStore:setDocValue( assetDoc1 ) )
		
		-- Read favorites for asset
		
		local getFavorites = rxTest:observe( 
				callFunctionOrSubmodel(
					rxTest, catalog,
					'WFCatCollaborationActivity', 'getFavoritesForAsset', catalog, albumId, assetId )
					:map( function( favorites )
						return favorites and #favorites or 0
					end ) )
		
		getFavorites:expectDataWithinTime( 3, 0 )
		
		-- Add a favorite
		
		rxTest:expectOnlyCompleted( 				
				callFunctionOrSubmodel(
					rxTest, catalog,
					'WFCatCollaborationActivity', 'addFavorite', catalog, albumId, assetId ) )
		
		getFavorites:expectDataWithinTime( 3, 1 )
		
		-- Make the favorite look like it has the feed back user ID populated via Oz.
		
		local favoriteId
		
		rxTest:waitFor( catalog:indexStore():queryOnce( {
				sql = "SELECT docId FROM spacefavorite",
				quiesceUntilUpToDate = true
			} )
			:map( function( rows )
				favoriteId = rows[ 1 ][ 1 ]
			end ) )
		
		rxTest:waitFor( docStore:applyOverlay( {
				_id = favoriteId,
				author = {
					id = feedbackUserId
				}
			} ) )
		
		-- Remove the favorite
		
		rxTest:expectOnlyCompleted( 				
				callFunctionOrSubmodel(
					rxTest, catalog,
					'WFCatCollaborationActivity', 'removeFavorite', catalog, albumId, assetId ) )
		
		getFavorites:expectDataWithinTime( 3, 0 )
		
		getFavorites:dispose()
		
	end

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

	function WFCatCollaborationActivityTest.rxTestGetCommentsForAlbumByAssetId( rxTest )

		rxTest:setTimeLimit( 10 )
		
		local catalog = WFCatCollaborationActivityTestUtils.createFakeWFCatalog( rxTest )
		local docStore = catalog:docStore()
		
		local albumInfo, assetInfo = WFCatCollaborationActivityTestUtils.createSharedAlbumWithAsset( rxTest, catalog )
		
		local getCommentsByLocalId = rxTest:observe( 
				callFunctionOrSubmodel(
					rxTest, catalog,
					'WFCatCollaborationActivity', 'getCommentsForAlbumByAssetId', catalog, albumInfo.localId, { assetInfo.localId } ) )
		
		local getCommentsByFullId = rxTest:observe( 
				callFunctionOrSubmodel(
					rxTest, catalog,
					'WFCatCollaborationActivity', 'getCommentsForAlbumByAssetId', catalog, albumInfo.localId, { assetInfo.globalId } ) )
		
		getCommentsByLocalId:expectDataWithinTime( 3, {} )
		
		getCommentsByFullId:expectDataWithinTime( 3, {} )
		
		-- Simulate already added comments
		
		local currUserId = catalog:ozUserId()
		local commentBody = "comment1"
		local comments = {
			WFCatCollaborationActivityTestUtils.createComment( albumInfo.spaceId, assetInfo.globalId, currUserId, commentBody ),
		}
		
		rxTest:expectOnlyCompleted(
			docStore:bulkSetDocValue( comments )
				:takeLast( 0 ) )
		
		-- Verify getCommentsForAlbumByAssetId triggers with update.
		
		getCommentsByLocalId:expectDataWithinTime( 3, {
			[ assetInfo.localId ] = true
		} )
		
		getCommentsByFullId:expectDataWithinTime( 3, {
			[ assetInfo.globalId ] = true
		} )
		
		getCommentsByLocalId:dispose()
		
		getCommentsByFullId:dispose()
		
	end

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

	function WFCatCollaborationActivityTest.rxTestGetFavoritesForAlbumByAssetId( rxTest )

		rxTest:setTimeLimit( 10 )
		
		local catalog = WFCatCollaborationActivityTestUtils.createFakeWFCatalog( rxTest )
		local docStore = catalog:docStore()
		
		local albumInfo, assetInfo = WFCatCollaborationActivityTestUtils.createSharedAlbumWithAsset( rxTest, catalog )
		
		local getFavoritesByLocalId = rxTest:observe( 
				callFunctionOrSubmodel(
					rxTest, catalog,
					'WFCatCollaborationActivity', 'getFavoritesForAlbumByAssetId', catalog, albumInfo.localId, { assetInfo.localId } ) )
		
		local getFavoritesByFullId = rxTest:observe( 
				callFunctionOrSubmodel(
					rxTest, catalog,
					'WFCatCollaborationActivity', 'getFavoritesForAlbumByAssetId', catalog, albumInfo.localId, { assetInfo.globalId } ) )
		
		getFavoritesByLocalId:expectDataWithinTime( 3, {} )
		
		getFavoritesByFullId:expectDataWithinTime( 3, {} )
		
		-- Simulate already added favorite
		
		local currUserId = catalog:ozUserId()
		local favoriteDoc1 = WFCatCollaborationActivityTestUtils.createFavorite( albumInfo.spaceId, assetInfo.globalId, currUserId )
		rxTest:expectOnlyCompleted(
			docStore:bulkSetDocValue( { favoriteDoc1 } )
				:takeLast( 0 ) )
		
		-- Verify getFavoritesForAlbumByAssetId triggers with update.
		
		getFavoritesByLocalId:expectDataWithinTime( 3, {
			[ assetInfo.localId ] = true
		} )
		
		getFavoritesByFullId:expectDataWithinTime( 3, {
			[ assetInfo.globalId ] = true
		} )
		
		getFavoritesByLocalId:dispose()
		
		getFavoritesByFullId:dispose()
		
	end

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

	function WFCatCollaborationActivityTest.rxTestGetCommentedAlbumsForAssetId( rxTest )

		rxTest:setTimeLimit( 10 )
		
		local catalog = WFCatCollaborationActivityTestUtils.createFakeWFCatalog( rxTest )
		local docStore = catalog:docStore()
		
		local albumInfo, assetInfo = WFCatCollaborationActivityTestUtils.createSharedAlbumWithAsset( rxTest, catalog )
		
		local getCommentedAlbumsByLocalId = rxTest:observe( 
				callFunctionOrSubmodel(
					rxTest, catalog,
					'WFCatCollaborationActivity', 'getCommentedAlbumsForAssetId', catalog, assetInfo.localId ) )
		
		local getCommentedAlbumsByFullId = rxTest:observe( 
				callFunctionOrSubmodel(
					rxTest, catalog,
					'WFCatCollaborationActivity', 'getCommentedAlbumsForAssetId', catalog, assetInfo.globalId ) )
		
		getCommentedAlbumsByLocalId:expectDataWithinTime( 3, {} )
		
		getCommentedAlbumsByFullId:expectDataWithinTime( 3, {} )
		
		-- Simulate already added comments
		
		local currUserId = catalog:ozUserId()
		local commentBody = "comment1"
		local comments = {
			WFCatCollaborationActivityTestUtils.createComment( albumInfo.spaceId, assetInfo.globalId, currUserId, commentBody ),
		}
		
		rxTest:expectOnlyCompleted(
			docStore:bulkSetDocValue( comments )
				:takeLast( 0 ) )
		
		-- Verify getCommentedAlbumsForAssetId triggers with update.
		
		local expectedDocId = albumInfo.localId
		
		-- Because mobile only deals with globalId
		if WFPlatformInfo.isMobile() then
			expectedDocId = albumInfo.globalId
		end
		
		getCommentedAlbumsByLocalId:expectDataWithinTime( 3, {
			{
				docId = expectedDocId,
				albumName = 'WFCatCollaboration',
				commentsCount = 1,
			},
		} )
		
		getCommentedAlbumsByFullId:expectDataWithinTime( 3, {
			{
				docId = expectedDocId,
				albumName = 'WFCatCollaboration',
				commentsCount = 1,
			},
		} )
		
		getCommentedAlbumsByLocalId:dispose()
		
		getCommentedAlbumsByFullId:dispose()
		
	end


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

	function WFCatCollaborationActivityTest.rxTestGetFavoritedAlbumsForAssetId( rxTest )

		rxTest:setTimeLimit( 10 )
		
		local catalog = WFCatCollaborationActivityTestUtils.createFakeWFCatalog( rxTest )
		local docStore = catalog:docStore()
		
		local albumInfo, assetInfo = WFCatCollaborationActivityTestUtils.createSharedAlbumWithAsset( rxTest, catalog )
		
		local getFavoritedAlbumsByLocalId = rxTest:observe( 
				callFunctionOrSubmodel(
					rxTest, catalog,
					'WFCatCollaborationActivity', 'getFavoritedAlbumsForAssetId', catalog, assetInfo.localId ) )
		
		local getFavoritedAlbumsByFullId = rxTest:observe( 
				callFunctionOrSubmodel(
					rxTest, catalog,
					'WFCatCollaborationActivity', 'getFavoritedAlbumsForAssetId', catalog, assetInfo.globalId ) )
		
		getFavoritedAlbumsByLocalId:expectDataWithinTime( 3, {} )
		
		getFavoritedAlbumsByFullId:expectDataWithinTime( 3, {} )
		
		-- Simulate already added favorites
		
		local currUserId = catalog:ozUserId()
		local favorites = {
			WFCatCollaborationActivityTestUtils.createFavorite( albumInfo.spaceId, assetInfo.globalId, currUserId ),
		}
		
		rxTest:expectOnlyCompleted(
			docStore:bulkSetDocValue( favorites )
				:takeLast( 0 ) )
		
		-- Verify getFavoritedAlbumsForAssetId triggers with update.
		
		local expectedDocId = albumInfo.localId
		
		-- Because mobile only deals with globalId
		if WFPlatformInfo.isMobile() then
			expectedDocId = albumInfo.globalId
		end
		
		getFavoritedAlbumsByLocalId:expectDataWithinTime( 3, {
			{
				docId = expectedDocId,
				albumName = 'WFCatCollaboration',
				favoritesCount = 1,
			},
		} )
		
		getFavoritedAlbumsByFullId:expectDataWithinTime( 3, {
			{
				docId = expectedDocId,
				albumName = 'WFCatCollaboration',
				favoritesCount = 1,
			},
		} )
		
		getFavoritedAlbumsByLocalId:dispose()
		
		getFavoritedAlbumsByFullId:dispose()
		
	end

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

	return maybeExistingTestClass and WFCatCollaborationActivityTest or 
			WFRxTestCase.wrapSuite( WFCatCollaborationActivityTest )

end
