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

PixelProviderChooseRenditionStrategyTaskTest.lua

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

ADOBE CONFIDENTIAL
------------------
Copyright 2022 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.
------------------------------------------------------------------------------]]

if not require 'WFPlatformInfo'.hasACR then 

	return {} 

end

	-- wf.core
local WFRxTestCase = require 'WFRxTestCase'
local WFCatMockCatalog = require 'WFCatMockCatalog'
local WFFileUtils = require 'WFFileUtils'
local KSPathUtils = require 'KSPathUtils'
local KSIdGenerator = require 'KSIdGenerator'

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

local PixelPathProviderScheduler = require "PixelPathProviderScheduler"
local PixelPathProviderRequestTypes = require "PixelPathProviderRequestTypes"
local PixelPathProviderStateMachine = require "PixelPathProviderStateMachine"

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

local function makeSchedulerForTest( rxTest )

	local catalog = WFCatMockCatalog.createFakeWFCatalog( rxTest )

	local scheduler = PixelPathProviderScheduler( catalog )

	rxTest:finally( function() scheduler:close() end )

	return scheduler

end

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

local function rxTestNeedsExternalImageXMP( rxTest )

	local scheduler = makeSchedulerForTest( rxTest )

	local SchedulerTestAPI = scheduler:_expose_test_API()

	local pixStreamId = "pixStreamId"

	local localAssetId = 1

	local renditionPath = 
			WFFileUtils.ensureFileNameIsUnique( 
					KSPathUtils.child( 
						KSPathUtils.getStandardFilePath( "temp" ),
						"fake" ) )

	local digest = 'digest'

	local revId = KSIdGenerator.uuidInLowercaseHex()

	local userOrientation = 1

	SchedulerTestAPI.addRunLoopTaskToAllowlist( 
		scheduler, 
		"PixelProviderChooseRenditionStrategyTask" )

	SchedulerTestAPI.runScheduledRequests( scheduler )

	local baseRenderInfoCache = 
			SchedulerTestAPI.getBaseRenderInfoCache( scheduler )

	local activeRenditionInfoCache = 
			SchedulerTestAPI.getSharedRenderCache( 
				scheduler, "activeRenditionInfoCache" )

	local currRenderSettingsCache = 
			SchedulerTestAPI.getSharedRenderCache( 
				scheduler, "currRenderSettingsCache" )

	SchedulerTestAPI.setTaskState( 
		scheduler, "PixelProviderChooseRenditionStrategyTask",
		"renditionPathBaseDir", "not used" )

	scheduler
		:addRequest( 
			pixStreamId, localAssetId,
			PixelPathProviderRequestTypes.names.grid_visible, 1 )

	for _, initialState in pairs( 
			{
				PixelPathProviderStateMachine.PixelCacheCheckStates.ChooseRenditionStrategy,
				PixelPathProviderStateMachine.PixelCacheCheckStates.ChooseRenderOnlyRenditionStrategy,
			} ) do

		for _, hasLocalOriginal in pairs( { true, false } ) do

			for _, assetSubType in pairs( { "image", "video", "deleted_video" } ) do

				rxTest:logf( "pushing cache data for asset of type %s", assetSubType )

				baseRenderInfoCache	
					:pushCacheItem( localAssetId, 
						{
							subtype = assetSubType,
							isVideo = assetSubType ~= "image",
							ozValidOriginalLink = "fake rel href to master",
							originalPath = hasLocalOriginal and "yes" or nil,
						} )

				activeRenditionInfoCache	
					:pushCacheItem( 
						pixStreamId,
						localAssetId, 
						{
							renditionPath = renditionPath,
							digest = digest,
							revId = revId,
							renderSize = 640,
							croppedLongSide = 1280,
							userOrientation = userOrientation, 
						} )

				currRenderSettingsCache	
					:pushCacheItem( localAssetId, 
						{
							digest,
							revId,
							nil, -- xmpCameraRaw is initially nil for external xmp
							nil, -- videoAdjustments
							userOrientation,
							nil -- video temporal info
						} )

				SchedulerTestAPI.setState( 
					scheduler, pixStreamId, localAssetId, initialState )

				SchedulerTestAPI.runScheduledRequests( scheduler )

				local expectedState = 
						( assetSubType == "image" and
							PixelPathProviderStateMachine.LocalBinaryPathCheckStates.RenditionStrategyNeedCheckIfExternalXmpDevelopIsLocal ) or
						( hasLocalOriginal and
							PixelPathProviderStateMachine.LocalBinaryPathCheckStates.NeedCheckAnyLocalNegativeForRender ) or
						( initialState ~=
								PixelPathProviderStateMachine.PixelCacheCheckStates.ChooseRenderOnlyRenditionStrategy and
							PixelPathProviderStateMachine.DownloadStates.NeedOriginalDownloadForRender or
							PixelPathProviderStateMachine.SendDataStates.SendNoDownloadableRenderOrBinary ) or
						string.format( "%s %s", initialState, assetSubType )

				local localAssetIdRequests = 
						SchedulerTestAPI.getAllLocalAssetIdRequests( scheduler, localAssetId )
						
				rxTest:expectEqual( #localAssetIdRequests, 1 )

				local actualPixStreamId, actualLocalAssetId, _, _, actualState = 
						unpack( localAssetIdRequests[ 1 ] or {} )

				rxTest:expectEqual( pixStreamId, actualPixStreamId )

				rxTest:expectEqual( localAssetId, actualLocalAssetId )

				rxTest:logf( "Initial state %s for %s asset that has %s local original, and is missing in memory transitioned to state %s and we are expecting state %s",
								initialState, assetSubType, 
								hasLocalOriginal and "a" or "NO", 
								actualState, expectedState )

				rxTest:expectEqual( expectedState, actualState )

			end

		end

	end

end

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

local function rxTest1280RenderStrategy( rxTest )

	rxTest:setTimeLimit( 5 * 60 )
	
	-- testing that we render 1280 locally when we can

	local scheduler = makeSchedulerForTest( rxTest )

	local SchedulerTestAPI = scheduler:_expose_test_API()

	local pixStreamId = "pixStreamId"

	local localAssetId = 1

	local renditionPath = 
			WFFileUtils.ensureFileNameIsUnique( 
					KSPathUtils.child( 
						KSPathUtils.getStandardFilePath( "temp" ),
						"fake" ) )

	local digest = 'digest'

	local revId = KSIdGenerator.uuidInLowercaseHex()

	local userOrientation = 1

	SchedulerTestAPI.addRunLoopTaskToAllowlist( 
		scheduler, 
		"PixelProviderChooseRenditionStrategyTask" )

	SchedulerTestAPI.runScheduledRequests( scheduler )

	local baseRenderInfoCache = 
			SchedulerTestAPI.getBaseRenderInfoCache( scheduler )

	local activeRenditionInfoCache = 
			SchedulerTestAPI.getSharedRenderCache( 
				scheduler, "activeRenditionInfoCache" )

	local currRenderSettingsCache = 
			SchedulerTestAPI.getSharedRenderCache( 
				scheduler, "currRenderSettingsCache" )

	SchedulerTestAPI.setTaskState( 
		scheduler, 
			"PixelProviderChooseRenditionStrategyTask", "renditionPathBaseDir",
			"not used" )

	scheduler
		:addRequest( 
			pixStreamId, localAssetId,
			PixelPathProviderRequestTypes.names.grid_visible, 1 )

	local initialState = PixelPathProviderStateMachine.PixelCacheCheckStates.ChooseRenditionStrategy

	for _, renditionSize in pairs( { 320, 640, 1280, 2048 } ) do
		for _, downloadableRenditionsStatus in pairs( { false, "valid", "invalid" } ) do
			for _, maybeOzLinkType in pairs( { false, "original", "proxy" } ) do
				for _, maybeLocalFileType in pairs( { false, "original", "proxy" } ) do
				for _, hasDevSettingsXmpInMemory in pairs( { false, true } ) do

					rxTest:log( "pushing cache data for asset of type image" )

					local renditionHrefs = { { size = renditionSize, href = "fakeURI" } }

					baseRenderInfoCache	
						:pushCacheItem( localAssetId, 
							{
								subtype = "image",
								isVideo = false,
								croppedLongSide = 6400,
								ozValidOriginalLink = maybeOzLinkType == "original" and
														"fake rel href to master" or nil,
								proxies = maybeOzLinkType == "proxy" and
													{ { href = "proxyHref", size = 2560 } } or nil,
								originalPath = maybeLocalFileType == "original" and "yes" or nil,
								proxyPath = maybeLocalFileType == "proxy" and "yes" or nil,
								renditions = downloadableRenditionsStatus == "valid" and
												renditionHrefs or nil,
								invalid_renditions = downloadableRenditionsStatus == "invalid" and
												renditionHrefs or nil,
							} )

					activeRenditionInfoCache	
						:pushCacheItem( 
							pixStreamId,
							localAssetId, 
							{
								renditionPath = renditionPath,
								digest = digest,
								revId = revId,
								renderSize = renditionSize,
								croppedLongSide = 6400,
								userOrientation = userOrientation, 
							} )

					currRenderSettingsCache	
						:pushCacheItem( localAssetId, 
							{
								digest,
								revId,
								hasDevSettingsXmpInMemory and "<xmp />" or nil,
								nil, -- videoAdjustments
								userOrientation,
								nil -- video temporal info
							} )

					SchedulerTestAPI.setState( 
						scheduler, pixStreamId, localAssetId, initialState )

					SchedulerTestAPI.runScheduledRequests( scheduler )

					local maybeCanRenderState =
							( maybeLocalFileType and
								PixelPathProviderStateMachine.LocalBinaryPathCheckStates.NeedCheckAnyLocalNegativeForRender ) or
							( maybeOzLinkType == "original" and
								PixelPathProviderStateMachine.DownloadStates.NeedOriginalDownloadForRender ) or
							( maybeOzLinkType == "proxy" and
								PixelPathProviderStateMachine.DownloadStates.NeedProxyDownloadForRender ) or
							nil

					-- if we are going to render but don't have xmp in memory yet we will
					-- transition to a state that will read xmp into memory
					maybeCanRenderState = 
						maybeCanRenderState and 
							( hasDevSettingsXmpInMemory and 
								maybeCanRenderState or
								PixelPathProviderStateMachine.LocalBinaryPathCheckStates.RenditionStrategyNeedCheckIfExternalXmpDevelopIsLocal ) or
						nil

					local expectedState =
								-- no downloadable renditions? then try render or fail
								( not downloadableRenditionsStatus and 
									( maybeCanRenderState or
										PixelPathProviderStateMachine.SendDataStates.SendNoDownloadableRenderOrBinary ) ) or
								-- no valid downloadable renditions? then try render or download the invalid one
								( downloadableRenditionsStatus == "invalid" and 
									( maybeCanRenderState or
										PixelPathProviderStateMachine.DownloadStates.NeedInvalidRenderDownload ) ) or
								-- if we have a downloadable render, download based on rendition size and local file state
								( downloadableRenditionsStatus == "valid" and 
									( renditionSize == 1280 and maybeLocalFileType and 
										maybeCanRenderState or
										PixelPathProviderStateMachine.DownloadStates.NeedRenderDownload ) ) or 
								"cannot determine expected state"

					local localAssetIdRequests = 
							SchedulerTestAPI.getAllLocalAssetIdRequests( scheduler, localAssetId )
							
					rxTest:expectEqual( #localAssetIdRequests, 1 )

					local actualPixStreamId, actualLocalAssetId, _, _, actualState = 
							unpack( localAssetIdRequests[ 1 ] or {} )

					rxTest:expectEqual( pixStreamId, actualPixStreamId )

					rxTest:expectEqual( localAssetId, actualLocalAssetId )

					rxTest:logf( "Initial state %s for image asset rendition size %s downloadableRenditionsStatus %s maybeOzLinkType %s maybeLocalFileType %s hasDevSettingsXmpInMemory %s transitioned to state %s and we are expecting state %s",
									initialState,
									renditionSize,
									downloadableRenditionsStatus,
									maybeOzLinkType,
									maybeLocalFileType,
									hasDevSettingsXmpInMemory,
									actualState, expectedState )

					rxTest:expectEqual( expectedState, actualState )

				end
				end
			end
		end
	end

end

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

return WFRxTestCase.wrapSuite( 'PixelProviderChooseRenditionStrategyTaskTest', {

	rxTestNeedsExternalImageXMP = rxTestNeedsExternalImageXMP,

	rxTest1280RenderStrategy = rxTest1280RenderStrategy,

} )
