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

WFCatVideoTest.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.self_test
local WFRxTestCase = require 'WFRxTestCase'
local WFTestFileUtils = require 'WFTestFileUtils'

	-- WF.core.utils
local WFArguments = require 'WFArguments'
local KSIdGenerator = require 'KSIdGenerator'
local KSTableUtils = require 'KSTableUtils'
local KSPathUtils = require 'KSPathUtils'
local WFRxScheduler = require 'WFRxScheduler'
local WFPlatformInfo = require 'WFPlatformInfo'

	-- WF.oz_client.managed_catalog
local WFCatOzTestSession = require 'WFCatOzTestSession'
local WFCatBinaryUploader = require 'WFCatBinaryUploader'
local WFCatAssetTestUtils = require 'WFCatAssetTestUtils'
local WFCatTestSession = require 'WFCatTestSession'
local WFCatMetadataPuller = require 'WFCatMetadataPuller'
local WFCatMetadataPusher = require 'WFCatMetadataPusher'
local WFCatOzTestSession = require 'WFCatOzTestSession'
local WFCatSharedWithYouUtils = require 'WFCatSharedWithYouUtils'
local WFCatMockCatalog = require 'WFCatMockCatalog'
local WFCatVideo = require 'WFCatVideo'

	-- WF.web.json
local KSJsonEncoder = require 'KSJsonEncoder'

local check = assert( WFArguments.check )
local derefOpt = assert( KSTableUtils.derefOpt )
local WFCatMockCatalog_createFakeWFCatalog = assert( WFCatMockCatalog.createFakeWFCatalog )

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

local WFCatVideoTest = {}

local options = {

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

	isCatalogPuller = true

}

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

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

local function setupCatalogAndDocStore( rxTest )

	local catalogTestSession = WFCatTestSession( rxTest )

	local catalog, catalogSpec, catalogId, docStore

	rxTest:waitFor(

		catalogTestSession:catalog()
			:tap( function( _catalog )
				check( 'WFCatalog' )
				catalog = _catalog
				catalogSpec = _catalog:ozCatalogSpec()
				catalogId = _catalog:ozCatalogSpec():catalogId()
				docStore = catalog:docStore()
			end ) )

	return catalogTestSession, catalog, catalogSpec, catalogId, docStore

end

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

local function generateProxiesForVideoOne( rxTest, optArgs )

	rxTest:setTimeLimit( 240 )

	-- Have a reference to catalogTestSession in case it will be GCed before the puller use it.
	local _, catalog, catalogSpec, catalogId = setupCatalogAndDocStore( rxTest )

	-- allow_direct_upload is set to true by default
	-- rxTest:waitFor( catalog:ozUser():enableFeature( 'allow_direct_upload' ) )
	rxTest:waitFor( catalog:ozUser():getAccountDocFromOz() )

	local pusher = WFCatMetadataPusher( catalog, options )
	rxTest:addCloseTarget( pusher )

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

	local uploader = WFCatBinaryUploader( catalog, nil, uploaderTaskDelays, catalogSpec, {
			clearFromRecentlyUploadedSeconds = 1,
			waitForOtherUploadSeconds = .5,
			waitForCopyFailedSeconds = .5,
			timer = function( seconds )
				   return Observable.timer( seconds, WFRxScheduler.sharedScheduler() )
			end,
			forceIncludeProgress = true
		} )

	local assetId = KSIdGenerator.uuidInLowercaseHex()
	local revisionId = KSIdGenerator.uuidInLowercaseHex()

	local testDataPath = KSPathUtils.child( KSPathUtils.getStandardFilePath( 'testdata' ), "import-samples" )
	local testDataFolder1 = KSPathUtils.child( testDataPath, "folder-1" )
	local originalFilePath = KSPathUtils.child( testDataFolder1, "IMG_7772.mp4" )
	local sha256 = require 'WFCrypto'.digestFile( originalFilePath, 'SHA256' )

	local assetDoc = WFCatAssetTestUtils.createBaseAssetDocument( catalogId, assetId, revisionId, sha256, originalFilePath )
	assetDoc = WFCatAssetTestUtils.addOriginalPathToDocument(assetDoc, sha256, originalFilePath)
	rxTest:waitFor( catalog:docStore():setDocValue( assetDoc ))

	-- start up sync engine

	rxTest:waitFor( pusher:sendUpdatesContinuously() )
	puller:getUpdatesContinuously()
	
	rxTest:observe( catalog:docStore():ongoingDocValue( assetId )
		:map( function( docValue )
			return derefOpt( docValue, '_serverProvidedMetadata' ) ~= nil
		end ) )
		:expectDataWithinTime( 30, true )
		:dispose()
	
	-- before original is uploaded, generateProxies request should be ignored
	
	rxTest:expectSingleValue( WFCatVideo.generateProxies( catalog, assetId, optArgs ),
				false, 'original does not exist' )
	
	-- upload original binary
	
	uploader:startContinuousUploads()

	local uploading = rxTest:observe( uploader:isDoingWork() )
	uploading:expectDataWithinTime( 60, false )

	local docObserver = rxTest:observe( catalog:docStore():ongoingDocValue( assetId )
		:map( function( docValue )
			if derefOpt( docValue, '_serverProvidedMetadata', 'links', '/rels/master', 'href') and
					derefOpt( docValue, '_serverProvidedMetadata', 'links', '/rels/proxy_type/1080p', 'href') then
				
				-- For Videos, the 1080p proxy is created when renditions are generated, as it
				-- is also used as a rendition.
				return true
			end
		end ) )

	docObserver:expectDataWithinTime( 180, true )

	if optArgs and optArgs.specialProxy == 'bt709' then
		
		-- Now we call WFCatVideo.generateProxies to let oz generate proxy for bt709
		
		rxTest:waitFor( WFCatVideo.generateProxies( catalog, assetId, optArgs ) )
	
		docObserver = rxTest:observe( catalog:docStore():ongoingDocValue( assetId )
		:map( function( docValue )
			return derefOpt( docValue, '_serverProvidedMetadata', 'links', '/rels/proxy_type/1080p709', 'href') ~= nil
		end ) )
	
		docObserver:expectDataWithinTime( 180, true )
	
		rxTest:expectSingleValue( WFCatVideo.generateProxies( catalog, assetId, optArgs ),
				false, 'already exists' )

	end

end

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

function WFCatVideoTest.rxTestGenerateProxiesForVideoOne_testNightly( rxTest )

	generateProxiesForVideoOne( rxTest )

end

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

if WFPlatformInfo.isWindows then
	function WFCatVideoTest.rxTestGenerateProxiesForVideoOne_specialProxy_bt709_testNightly( rxTest )

		generateProxiesForVideoOne( rxTest, { specialProxy = 'bt709' } )

	end
end

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

local function generateProxiesOrRenditionsForSpaceVideoOne( rxTest, optArgs )

	rxTest:setTimeLimit( 240 )

	optArgs = optArgs or {}

	local spaceUserRole = 'contributor'
	if optArgs.generateType == 'proxy' then
		spaceUserRole = 'editor'
	end

	local uploadOriginalBinary = true
	local useVideo = true
	local doNotGenerateRenditions = true
		-- For Videos, the 1080p proxy is created when renditions are generated, as it
		-- is also used as a rendition.

	local _, _, _,
			memberWFCatalog, _, _,
			spaceId, _, _, _ = WFCatOzTestSession.setupSpaceOzTest(
					rxTest, spaceUserRole, nil, uploadOriginalBinary, useVideo, doNotGenerateRenditions )

	local spaceFeedArgs = { isPrefetchEnabled = true }
	local spaceFeedsManager = WFCatOzTestSession.createSpaceFeedsManager( rxTest, memberWFCatalog, spaceFeedArgs )

	spaceFeedsManager:reportCatalogInitialSyncIsComplete()
	spaceFeedsManager:startFetchingUpdates()
	spaceFeedsManager:startSendingUpdates()

	local memberAssetId

	local querySpaceAssetIdStr
	if WFPlatformInfo.isDesktop then
		querySpaceAssetIdStr = [[SELECT album_asset_v2.assetId
								FROM albums INNER JOIN album_asset_v2 ON albums.albumId == album_asset_v2.albumId
								WHERE spaceId == ?]]
	else
		querySpaceAssetIdStr = [[SELECT album_asset.assetId
								FROM albums INNER JOIN album_asset ON albums.docId == album_asset.albumId
								WHERE spaceId == ?]]
	end

	rxTest:observe(
		memberWFCatalog:indexStore():query{
				sql = querySpaceAssetIdStr, spaceId,
				singleColumnQuery = true
			}
			:map( function( assetIds )
				memberAssetId = assetIds[ 1 ]
				return #assetIds == 1
			end ) )
		:expectDataWithinTime( 90, true )

	spaceFeedsManager:stopFetchingUpdates()
	spaceFeedsManager:stopSendingUpdates()

	if optArgs.generateType == 'proxy' then

		-- Check if assetDoc is editable, has master link and no proxies link
		rxTest:expectSingleValue( memberWFCatalog:docStore():docValue( memberAssetId )
			:map( function( assetDoc )
				return WFCatSharedWithYouUtils.canEditAsset( assetDoc )
					and derefOpt( assetDoc, '_serverProvidedMetadata', 'links', '/rels/master', 'href')
					and not derefOpt( assetDoc, '_serverProvidedMetadata', 'links', '/rels/proxy_type/1080p', 'href')
					and not derefOpt( assetDoc, '_serverProvidedMetadata', 'links', '/rels/proxy_type/1080p709', 'href')
			end ),
			true
		)

		-- Now we call WFCatVideo.generateProxiesForSpaceAsset to let oz generate proxies for space asset
		rxTest:waitFor( WFCatVideo.generateProxiesForSpaceAsset( memberWFCatalog, spaceId, memberAssetId,
							{ specialProxy = optArgs.specialProxyOrRendition } ) )

	elseif optArgs.generateType == 'rendition' and optArgs.specialProxyOrRendition == 'bt709' then

		-- Check if assetDoc has master link and no speical rendition link
		rxTest:expectSingleValue( memberWFCatalog:docStore():docValue( memberAssetId )
			:map( function( assetDoc )
				return derefOpt( assetDoc, '_serverProvidedMetadata', 'links', '/rels/master', 'exists' )
					and not derefOpt( assetDoc, '_serverProvidedMetadata', 'links', '/rels/rendition_type/1080p709', 'href')
			end ),
			true
		)

		-- Now we call WFCatVideo.generateProxiesForSpaceAsset to let oz generate special rendition for space asset
		rxTest:waitFor( WFCatVideo.generateSpecialRenditionForSpaceAsset( memberWFCatalog, spaceId, memberAssetId, optArgs.specialProxyOrRendition ) )

	end

	spaceFeedsManager:startFetchingUpdates()
	spaceFeedsManager:startSendingUpdates()

	local docObserver = rxTest:observe( memberWFCatalog:docStore():ongoingDocValue( memberAssetId )
	:map( function( docValue )

		local links = derefOpt( docValue, '_serverProvidedMetadata', 'links' )

		if optArgs.generateType == 'proxy' then

			local proxyLink

			if optArgs.specialProxyOrRendition == 'bt709' then
				proxyLink = derefOpt( links, '/rels/proxy_type/1080p709', 'href')
			else
				proxyLink = derefOpt( links, '/rels/proxy_type/1080p', 'href')
			end

			return proxyLink ~= nil

		elseif optArgs.generateType == 'rendition' and optArgs.specialProxyOrRendition == 'bt709' then

			local renditionLink = derefOpt( links, '/rels/rendition_type/1080p709', 'href')

			return renditionLink ~= nil

		end

		return false

	end ) )

	docObserver:expectDataWithinTime( 180, true )

	-- Check if we retry requesting special proxy or rendition, the request should be ignored

	if optArgs.specialProxyOrRendition == 'bt709' then

		if optArgs.generateType == 'proxy' then

			rxTest:expectSingleValue( WFCatVideo.generateProxiesForSpaceAsset( memberWFCatalog, spaceId, memberAssetId,
							{ specialProxy = optArgs.specialProxyOrRendition } ),
					false, 'already exists' )

		elseif optArgs.generateType == 'rendition' then

			rxTest:expectSingleValue( WFCatVideo.generateSpecialRenditionForSpaceAsset( memberWFCatalog, spaceId, memberAssetId,
							optArgs.specialProxyOrRendition ),
					false, 'already exists' )

		end

	end

end

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

function WFCatVideoTest.rxTestGenerateProxiesForSpaceVideoOne_testNightly( rxTest )

	generateProxiesOrRenditionsForSpaceVideoOne( rxTest, { generateType = 'proxy' } )

end

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

if WFPlatformInfo.isWindows then
function WFCatVideoTest.rxTestGenerateProxiesForSpaceVideoOne_specialProxy_bt709_testNightly( rxTest )

	generateProxiesOrRenditionsForSpaceVideoOne( rxTest, { generateType = 'proxy', specialProxyOrRendition = 'bt709' } )

end

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

function WFCatVideoTest.rxTestGenerateRenditionsForSpaceVideoOne_specialRendition_bt709_testNightly( rxTest )

	generateProxiesOrRenditionsForSpaceVideoOne( rxTest, { generateType = 'rendition', specialProxyOrRendition = 'bt709' } )

end
end

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

local function generateProxiesOrRenditionsForSpaceVideoOne_withoutOriginalLink( rxTest, optArgs )

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

	local wfCatalog = WFCatMockCatalog_createFakeWFCatalog( rxTest, nil, nil, catalogOptArgs )
	
	local assetId = KSIdGenerator.uuidInLowercaseHex()
	local spaceId = KSIdGenerator.uuidInLowercaseHex()
	
	rxTest:waitFor( wfCatalog:docStore():applyOverlay{
		_id = assetId,
		_spaceId = spaceId,
		_serverProvidedMetadata = {
			catalog_doc = {
				id = KSIdGenerator.uuidInLowercaseHex()
			}
		}
	} )
	
	if optArgs.generateType == 'proxy' then

		rxTest:expectSingleValue( WFCatVideo.generateProxiesForSpaceAsset( wfCatalog, spaceId, assetId,
						{ specialProxy = optArgs.specialProxyOrRendition } ),
				false, 'original does not exist' )

	elseif optArgs.generateType == 'rendition' then

		rxTest:expectSingleValue( WFCatVideo.generateSpecialRenditionForSpaceAsset( wfCatalog, spaceId, assetId,
						optArgs.specialProxyOrRendition ),
				false, 'original does not exist' )

	end

end

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

function WFCatVideoTest.rxTestGenerateProxiesForSpaceVideoOne_withoutOriginalLink( rxTest )

	generateProxiesOrRenditionsForSpaceVideoOne_withoutOriginalLink( rxTest, { generateType = 'proxy' } )

end

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

if WFPlatformInfo.isWindows then
function WFCatVideoTest.rxTestGenerateProxiesForSpaceVideoOne_withoutOriginalLink_specialProxy_bt709( rxTest )

	generateProxiesOrRenditionsForSpaceVideoOne_withoutOriginalLink( rxTest, { generateType = 'proxy', specialProxyOrRendition = 'bt709' } )

end

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

function WFCatVideoTest.rxTestGenerateRenditionsForSpaceVideoOne_withoutOriginalLink_specialRendition_bt709( rxTest )

	generateProxiesOrRenditionsForSpaceVideoOne_withoutOriginalLink( rxTest, { generateType = 'rendition', specialProxyOrRendition = 'bt709' } )

end
end

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

if WFPlatformInfo.isMobile() then
function WFCatVideoTest.rxTestQueryStoreLocallyVideoStream( rxTest )

	rxTest:setTimeLimit( 5 )

	local optArgs = {
		indexDefinitions = 'LrmCatalogIndexDefinitions.lua'
	}
	local wfCatalog = WFCatMockCatalog.createFakeWFCatalog( rxTest, nil, nil, optArgs )

	local albumId = KSIdGenerator.uuidInLowercaseHex()

	local assetId_image = KSIdGenerator.uuidInLowercaseHex()
	local assetId_video = KSIdGenerator.uuidInLowercaseHex()

	local albumAssetId_image = KSIdGenerator.uuidInLowercaseHex()
	local albumAssetId_video = KSIdGenerator.uuidInLowercaseHex()


	-- create album
	rxTest:waitFor( wfCatalog:docStore():applyOverlay {
		type = 'album',
		_id = albumId,
		subtype = 'collection',
		name = 'test album'
	} )

	-- Add image
	rxTest:waitFor( wfCatalog:docStore():applyOverlay {
		type = 'asset',
		_id = assetId_image,
		subtype = 'image',
		_serverProvidedMetadata = {
			links = {
				[ '/rels/master' ] = {
					href = '/v1.0/catalogs/f50509f546184519afa38d4e55e442fc/assets/496e4bec7eff1bee558b4760ae00efa3/master',
				}
			},
		}
	} )

	rxTest:waitFor( wfCatalog:docStore():applyOverlay {
		type = 'album_asset',
		_id = albumAssetId_image,
		album = {
			id = albumId,
		},
		asset = {
			id = assetId_image,
		}
	} )

	-- Add video
	rxTest:waitFor( wfCatalog:docStore():applyOverlay {
		type = 'asset',
		_id = assetId_video,
		subtype = 'video',
		_serverProvidedMetadata = {
			links = {
				[ '/rels/master' ] = {
					href = '/v1.0/catalogs/f50509f546184519afa38d4e55e442fc/assets/496e4bec7eff1bee558b4760ae00efa3/master',
				}
			},
		}
	} )

	rxTest:waitFor( wfCatalog:docStore():applyOverlay {
		type = 'album_asset',
		_id = albumAssetId_video,
		album = {
			id = albumId,
		},
		asset = {
			id = assetId_video,
		}
	} )

	-- Observe queryStoreLocallyVideoStream
	local observer = rxTest:observe( WFCatVideo.DEBUG_queryStoreLocallyVideoStream( wfCatalog, 0.2 ) )

	observer:expectDataWithinTime( 1, {} )

	-- set album to store locally
	rxTest:waitFor( wfCatalog:docStore():applyOverlay {
		_id = albumId,
		_localOnly = {
			useOffline = true,
		}
	} )

	observer:expectDataWithinTime( 1, { assetId_video } )

end

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

function WFCatVideoTest.rxTestQueryStoreLocallyVideoStream_space( rxTest )

	rxTest:setTimeLimit( 5 )

	local optArgs = {
		indexDefinitions = 'LrmCatalogIndexDefinitions.lua'
	}
	local wfCatalog = WFCatMockCatalog.createFakeWFCatalog( rxTest, nil, nil, optArgs )

	local albumId = KSIdGenerator.uuidInLowercaseHex()
	local spaceId = KSIdGenerator.uuidInLowercaseHex()
	local spaceUserId = KSIdGenerator.uuidInLowercaseHex()

	local assetId_image = KSIdGenerator.uuidInLowercaseHex()
	local assetId_video = KSIdGenerator.uuidInLowercaseHex()

	local albumAssetId_image = KSIdGenerator.uuidInLowercaseHex()
	local albumAssetId_video = KSIdGenerator.uuidInLowercaseHex()


	-- create album and space
	rxTest:waitFor(
		wfCatalog:docStore():bulkSetDocValue( {
			{
				type = 'album',
				_id = albumId,
				_spaceId = spaceId,
				subtype = 'collection',
				name = 'test album'
			},
			{
				_id = KSIdGenerator.uuidInLowercaseHex(),
				type = 'space_album',
				space = {
					id = spaceId,
				},
				album = {
					id = albumId,
				}
			},
			{
				_id = spaceUserId,
				type = 'space_user',
				space = {
					id = spaceId
				},
				user = {
					id = KSIdGenerator.uuidInLowercaseHex()
				},
				status = "accepted",
				role = "editor",
			},
			{
				_id = spaceId,
				type = 'space',
				subtype = 'shared',
				download = false,
				private = false,
				location = false,
				metadata = false,
				_serverProvidedMetadata = {
					this_space_user = {
						id = spaceUserId
					}
				}
			}
		} )
	)

	-- Add image
	rxTest:waitFor( wfCatalog:docStore():applyOverlay {
		type = 'asset',
		_id = assetId_image,
		_spaceId = spaceId,
		subtype = 'image',
		_serverProvidedMetadata = {
			links = {
				[ '/rels/master' ] = {
					href = '/v1.0/catalogs/f50509f546184519afa38d4e55e442fc/assets/496e4bec7eff1bee558b4760ae00efa3/master',
				}
			},
		}
	} )

	rxTest:waitFor( wfCatalog:docStore():applyOverlay {
		type = 'album_asset',
		_id = albumAssetId_image,
		_spaceId = spaceId,
		album = {
			id = albumId,
		},
		asset = {
			id = assetId_image,
		}
	} )

	-- Add video
	rxTest:waitFor( wfCatalog:docStore():applyOverlay {
		type = 'asset',
		_id = assetId_video,
		_spaceId = spaceId,
		subtype = 'video',
		_serverProvidedMetadata = {
			links = {
				[ '/rels/master' ] = {
					href = '/v1.0/catalogs/f50509f546184519afa38d4e55e442fc/assets/496e4bec7eff1bee558b4760ae00efa3/master',
				}
			},
		}
	} )

	rxTest:waitFor( wfCatalog:docStore():applyOverlay {
		type = 'album_asset',
		_id = albumAssetId_video,
		_spaceId = spaceId,
		album = {
			id = albumId,
		},
		asset = {
			id = assetId_video,
		}
	} )

	-- Observe queryStoreLocallyVideoStream
	local observer = rxTest:observe( WFCatVideo.DEBUG_queryStoreLocallyVideoStream( wfCatalog, 0.2 ) )

	observer:expectDataWithinTime( 1, {} )

	-- set album to store locally
	rxTest:waitFor( wfCatalog:docStore():applyOverlay {
		_id = albumId,
		_localOnly = {
			useOffline = true,
		}
	} )

	observer:expectDataWithinTime( 1, { assetId_video } )

	-- change space_user to role viewer
	rxTest:waitFor( wfCatalog:docStore():applyOverlay {
		_id = spaceUserId,
		role = "viewer",
	} )

	observer:expectDataWithinTime( 1, {} )

end
end

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

if WFPlatformInfo.isMobile() then

function WFCatVideoTest.rxTestGetNeedGenerateProxiesAssetsInfo( rxTest )

	rxTest:setTimeLimit( 5 )

	local wfCatalog = WFCatMockCatalog.createFakeWFCatalog( rxTest )

	local assetId_image = KSIdGenerator.uuidInLowercaseHex()
	local assetId_video = KSIdGenerator.uuidInLowercaseHex()
	local assetId_video2 = KSIdGenerator.uuidInLowercaseHex()

	local spaceId = KSIdGenerator.uuidInLowercaseHex()

	rxTest:waitFor( wfCatalog:docStore():applyOverlay {
		type = 'asset',
		_id = assetId_image,
		subtype = 'image',
		_serverProvidedMetadata = {
			links = {
				[ '/rels/rendition_type/thumbnail2x' ] = {
					href = '/v1.0/catalogs/f50509f546184519afa38d4e55e442fc/assets/496e4bec7eff1bee558b4760ae00efa3/revisions/16b97d9d9e3042d09633c3878622d48a/renditions/835c23790d534b28b8b7bb99740d13ba',
				},
				[ '/rels/master' ] = {
					href = '/v1.0/catalogs/f50509f546184519afa38d4e55e442fc/assets/496e4bec7eff1bee558b4760ae00efa3/master',
				}
			},
		}
	} )

	-- assetIds only contains image
	rxTest:expectSingleValue(
		WFCatVideo.DEBUG_getNeedGenerateProxiesAssetsInfo( wfCatalog, { assetId_image } ),
		{} )

	-- Add video
	rxTest:waitFor( wfCatalog:docStore():applyOverlay {
		type = 'asset',
		_id = assetId_video,
		subtype = 'video',
		_serverProvidedMetadata = {
			links = {
				[ '/rels/rendition_type/thumbnail2x' ] = {
					href = '/v1.0/catalogs/f50509f546184519afa38d4e55e442fc/assets/496e4bec7eff1bee558b4760ae00efa3/revisions/16b97d9d9e3042d09633c3878622d48a/renditions/835c23790d534b28b8b7bb99740d13ba',
				},
				[ '/rels/master' ] = {
					href = '/v1.0/catalogs/f50509f546184519afa38d4e55e442fc/assets/496e4bec7eff1bee558b4760ae00efa3/master',
				}
			},
		}
	} )

	-- video 1.0 without proxy link
	rxTest:expectSingleValue(
		WFCatVideo.DEBUG_getNeedGenerateProxiesAssetsInfo( wfCatalog, { assetId_image, assetId_video } ),
		{{ assetId_video }} )

	-- Add video with spaceId
	rxTest:waitFor( wfCatalog:docStore():applyOverlay {
		type = 'asset',
		_id = assetId_video2,
		_spaceId = spaceId,
		subtype = 'video',
		_serverProvidedMetadata = {
			links = {
				[ '/rels/rendition_type/thumbnail2x' ] = {
					href = '/v1.0/catalogs/f50509f546184519afa38d4e55e442fc/assets/496e4bec7eff1bee558b4760ae00efa3/revisions/16b97d9d9e3042d09633c3878622d48a/renditions/835c23790d534b28b8b7bb99740d13ba',
				},
				[ '/rels/master' ] = {
					href = '/v1.0/catalogs/f50509f546184519afa38d4e55e442fc/assets/496e4bec7eff1bee558b4760ae00efa3/master',
				}
			},
		}
	} )

	-- video 1.0 without proxy link
	rxTest:expectSingleValue(
		WFCatVideo.DEBUG_getNeedGenerateProxiesAssetsInfo( wfCatalog, { assetId_image, assetId_video, assetId_video2 } ),
		{
			{ assetId_video },
			{ assetId_video2, spaceId }
		} )

	-- apply proxy link for video
	rxTest:waitFor( wfCatalog:docStore():applyOverlay {
		type = 'asset',
		_id = assetId_video,
		subtype = 'video',
		_serverProvidedMetadata = {
			links = {
				[ '/rels/proxy_type/1080p' ] = {
					href = '/v1.0/catalogs/f50509f546184519afa38d4e55e442fc/assets/496e4bec7eff1bee558b4760ae00efa3/revisions/16b97d9d9e3042d09633c3878622d48a/renditions/835c23790d534b28b8b7bb99740d13ba',
				}
			}
		}
	} )

	-- video proxy is generated for assetId_video
	rxTest:expectSingleValue(
		WFCatVideo.DEBUG_getNeedGenerateProxiesAssetsInfo( wfCatalog, { assetId_image, assetId_video, assetId_video2 } ),
		{{ assetId_video2, spaceId }} )

end

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

function WFCatVideoTest.rxTestGenerateProxiesForAssetIds_testNightly( rxTest )

	rxTest:setTimeLimit( 240 )

	local uploadOriginalBinary = true
	local useVideo = true
	local doNotGenerateRenditions = true
		-- For Videos, the 1080p proxy is created when renditions are generated, as it
		-- is also used as a rendition.

	local _, _, _,
			memberWFCatalog, memberCatalogSpec, _,
			spaceId, _, _, _ = WFCatOzTestSession.setupSpaceOzTest(
					rxTest, 'editor', nil, uploadOriginalBinary, useVideo, doNotGenerateRenditions )

	-- Add spaceFeedsManager

	local spaceFeedArgs = { isPrefetchEnabled = true }
	local spaceFeedsManager = WFCatOzTestSession.createSpaceFeedsManager( rxTest, memberWFCatalog, spaceFeedArgs )

	spaceFeedsManager:reportCatalogInitialSyncIsComplete()
	spaceFeedsManager:startFetchingUpdates()
	spaceFeedsManager:startSendingUpdates()

	-- Add member metadataPuller
	local pullerOptions = {
		continuousTaskDelays = {
			progressiveBackoff = false,
			noWorkDelay = 1,
			maxNoWorkDelay = 1,
			errorDelay = 1,
			maxDelay = 1,
		},
		catSpec = memberCatalogSpec,
		isCatalogPuller = true
	}

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

	puller:getUpdatesContinuously()

	local memberAssetId

	local querySpaceAssetIdStr
	if WFPlatformInfo.isDesktop then
		querySpaceAssetIdStr = [[SELECT album_asset_v2.assetId
								FROM albums INNER JOIN album_asset_v2 ON albums.albumId == album_asset_v2.albumId
								WHERE spaceId == ?]]
	else
		querySpaceAssetIdStr = [[SELECT album_asset.assetId
								FROM albums INNER JOIN album_asset ON albums.docId == album_asset.albumId
								WHERE spaceId == ?]]
	end

	rxTest:observe(
		memberWFCatalog:indexStore():query{
				sql = querySpaceAssetIdStr, spaceId,
				singleColumnQuery = true
			}
			:map( function( assetIds )
				memberAssetId = assetIds[ 1 ]
				return #assetIds == 1
			end ) )
		:expectDataWithinTime( 90, true )

	spaceFeedsManager:stopFetchingUpdates()
	spaceFeedsManager:stopSendingUpdates()

	-- Check if assetDoc is editable, has master link and no proxies link

	rxTest:expectSingleValue( memberWFCatalog:docStore():docValue( memberAssetId )
		:map( function( assetDoc )
			return WFCatSharedWithYouUtils.canEditAsset( assetDoc ) and
				derefOpt( assetDoc, '_serverProvidedMetadata', 'links', '/rels/master', 'href') and
				not derefOpt( assetDoc, '_serverProvidedMetadata', 'links', '/rels/proxy_type/1080p', 'href') and
				not derefOpt( assetDoc, '_serverProvidedMetadata', 'links', '/rels/proxy_type/1080p709', 'href')
		end ),
		true
	)

	-- Add another video to memberCatalog and sync
	local memberOnlyAssetId = KSIdGenerator.uuidInLowercaseHex()
	local memberOnlyAssetDocRevId = KSIdGenerator.uuidInLowercaseHex()

	local memberOnlyAssetDocPutUrl = string.format( '%s/assets/%s/revisions/%s',
										  memberCatalogSpec:catalogHref(),
										  memberOnlyAssetId, memberOnlyAssetDocRevId )

	local memberOnlyAssetDocContent = KSJsonEncoder.encodeOzUploadJson {
		user_id = memberCatalogSpec:wfOzUser():userId(),
		payload = WFCatOzTestSession.DEBUG_getAssetPayload( rxTest, memberCatalogSpec, true ),
		type = 'asset',
		subtype = 'video',
	}

	local memberOnlyAssetDocPutArgs = {
		requestHeaders = {
			{ header = 'Content-Type', value = 'application/json' },
			{ header = 'Accept', value = 'application/json' },
		},
	}

	rxTest:expectOnlyCompleted(
		memberCatalogSpec:put( memberOnlyAssetDocPutUrl, memberOnlyAssetDocContent, memberOnlyAssetDocPutArgs )
			:filter( function() return false end ) )

	-- upload member only asset original binary

	local memberOnlyAssetOriginalPutBinaryUrl = string.format( '%s/assets/%s/revisions/%s/master',
									  memberCatalogSpec:catalogHref(),
									  memberOnlyAssetId, memberOnlyAssetDocRevId )

	local tempTestFolder = WFTestFileUtils.createTestFolder( rxTest )
	local originalMockOrFilePath = WFCatAssetTestUtils.getTestDataOriginalFilePath( rxTest, tempTestFolder, 'IMG_7772.mp4' )

	local memberOnlyAssetOriginalPutBinaryArgs = {
		requestHeaders = {
			{ header = 'Content-Type', value = 'video/mp4' },
			{ header = "Accept", value = "application/json" },
		},
		dataFormat = 'filePath'
	}

	rxTest:waitFor( memberCatalogSpec:putBinary( memberOnlyAssetOriginalPutBinaryUrl, originalMockOrFilePath, memberOnlyAssetOriginalPutBinaryArgs ) )

	-- Check if memberOnlyAssetDoc has master link and no proxies link

	rxTest:observe( memberWFCatalog:docStore():ongoingDocValue( memberOnlyAssetId )
		:map( function( assetDoc )
			return derefOpt( assetDoc, '_serverProvidedMetadata', 'links', '/rels/master', 'href')
				and not derefOpt( assetDoc, '_serverProvidedMetadata', 'links', '/rels/proxy_type/1080p', 'href')
				and not derefOpt( assetDoc, '_serverProvidedMetadata', 'links', '/rels/proxy_type/1080p709', 'href')
		end ))
	:expectDataWithinTime( 30, true )
	:dispose()


	-- Now we call WFCatVideo.DEBUG_generateProxiesForAsetIds to let oz generate proxies for space and catalog videos

	rxTest:waitFor(
		WFCatVideo.DEBUG_generateProxiesForAsetIds( memberWFCatalog, {
			{ memberAssetId, spaceId },
			{ memberOnlyAssetId }
		} ) )

	-- Check if space asset has proxies generated

	spaceFeedsManager:startFetchingUpdates()
	spaceFeedsManager:startSendingUpdates()

	local docObserver = rxTest:observe( memberWFCatalog:docStore():ongoingDocValue( memberAssetId )
	:map( function( docValue )
		return derefOpt( docValue, '_serverProvidedMetadata', 'links', '/rels/proxy_type/1080p', 'href') ~= nil
	end ) )

	docObserver:expectDataWithinTime( 180, true )

	-- Check if catalog asset has proxies generated
	docObserver = rxTest:observe( memberWFCatalog:docStore():ongoingDocValue( memberOnlyAssetId )
	:map( function( docValue )
		return derefOpt( docValue, '_serverProvidedMetadata', 'links', '/rels/proxy_type/1080p', 'href') ~= nil
	end ) )

	docObserver:expectDataWithinTime( 180, true )

end

end

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

return WFRxTestCase.wrapSuite( 'WFCatVideoTest', WFCatVideoTest )
