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

NmbDocValueToRenderInfoTest.lua

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

ADOBE CONFIDENTIAL
___________________

Copyright 2020 Adobe

All Rights Reserved.

NOTICE: All information contained herein is, and remains
the property of Adobe and its suppliers, if any. The intellectual
and technical concepts contained herein are proprietary to Adobe
and its suppliers and are protected by all applicable intellectual
property laws, including trade secret and copyright laws.
Dissemination of this information or reproduction of this material
is strictly forbidden unless prior written permission is obtained
from Adobe.
------------------------------------------------------------------------------]]

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

local WFTableMerge = require "WFTableMerge"
local WFFileUtils = require "WFFileUtils"
local WFPlatformInfo = require "WFPlatformInfo"
local KSPathUtils = require "KSPathUtils"
local KSTableUtils = require "KSTableUtils"
local WFCatMockCatalog = require "WFCatMockCatalog"

    -- WF.oz_client.managed_catalog
local NmbDocValueToRenderInfo = require 'NmbDocValueToRenderInfo'

local derefOpt = assert( KSTableUtils.derefOpt )

local testPath = KSPathUtils.getStandardFilePath( 'testdata' )
local volumeGuid = WFFileUtils.getVolumeGuidForPath( testPath )

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

local function mergeAll( ... )

	local ret = {}

	for i = 1, select( "#", ... ) do

		ret = WFTableMerge.applyOverlay( ret, select( i, ... ) )

	end

	return ret

end

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

local _docValueWithoutSpaceID = {}

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

local _docValueWithSpaceID = { _spaceId = "yass" }

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

local _docValueWithDownloadableMaster =
	{ 
		_serverProvidedMetadata = {
			links = {
				[ "/rels/master" ] =  {
					href = "yass"
				}
			}
		}
	}

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

local _docValueWithLocalMaster =
	{
		_localOnly = {
			files = {
				original = {
					master = {
						relativePath = "yaas",
						volumeGuid = volumeGuid,
					}
				}
			}
		}
	}

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

local _docValueWithDownloadableProxy =
	{ 
		_serverProvidedMetadata = {
			links = {
				[ "/rels/proxy_type/2560" ] =  {
					href = "yass"
				}
			}
		}
	}

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

local _docValueWithLocalProxy =
	{
		_localOnly = {
			files = {
				proxy = {
					[ "2560" ] = {
						relativePath = "yaas",
						volumeGuid = volumeGuid,
					}
				}
			}
		}
	}

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

local _haveRenderableSourceFile = 
		{ _docValueWithDownloadableMaster, _docValueWithLocalMaster, 
			_docValueWithDownloadableProxy, _docValueWithLocalProxy }

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

local _docValueWithSharedEditable =
	{ _serverProvidedMetadata = { editable = "yass" } }

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

local function rxTestDisallowLocalEditsForDocValue( rxTest )

	rxTest:log( "testing non shared without renderable path" )

	rxTest
		:expectEqual(
			NmbDocValueToRenderInfo.disallowLocalEditsForDocValue(
				_docValueWithoutSpaceID ),
			true )

	rxTest:log( "testing shared without renderable path" )

	rxTest
		:expectEqual(
			NmbDocValueToRenderInfo.disallowLocalEditsForDocValue(
				_docValueWithSpaceID ),
			true )


	for haveRenderableSourceFileNum, docValueWithRenderableSourceFile in pairs( _haveRenderableSourceFile ) do

		rxTest:logf( "testing non shared renderable path %s", haveRenderableSourceFileNum )

		rxTest
			:expectEqual(
				NmbDocValueToRenderInfo.disallowLocalEditsForDocValue(
					mergeAll( _docValueWithoutSpaceID, docValueWithRenderableSourceFile ) ),
				false )

		rxTest:logf( "testing shared with renderable path %s", haveRenderableSourceFileNum )

		
		local shouldBlockEdit = derefOpt( docValueWithRenderableSourceFile, '_serverProvidedMetadata' ) ~= nil
			-- For assets that have been touched by Oz, rely on the `editable` field. Otherwise, enable editing
		
		rxTest
			:expectEqual(
				NmbDocValueToRenderInfo.disallowLocalEditsForDocValue(
					mergeAll( _docValueWithSpaceID, docValueWithRenderableSourceFile ) ),
				shouldBlockEdit )

		rxTest:logf( "testing editable shared with renderable path %s", haveRenderableSourceFileNum )

		rxTest
			:expectEqual(
				NmbDocValueToRenderInfo.disallowLocalEditsForDocValue(
					mergeAll( _docValueWithSpaceID, _docValueWithSharedEditable, docValueWithRenderableSourceFile ) ),
				false )

	end

end

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

local function rxTestExternalMasks( rxTest )

	local wfCatalog = WFCatMockCatalog.createFakeWFCatalog( rxTest )

	for _, hasMasksValue in pairs( { true, false } ) do
		for _, noMaskLinksValue in pairs( { true, false } ) do
			for _, noLocalMasksValue in pairs( { true, false } ) do

				local optArguments = {}

				if hasMasksValue then
					
					optArguments.hasMasks = true

				end

				if noMaskLinksValue then

					optArguments.noMaskLinks = true

				end

				if noLocalMasksValue then

					optArguments.noLocalMasks = true

				end

				local docValue = require "WFCatAssetTestUtils".createAssetDocument( 
									rxTest, wfCatalog, nil, optArguments )

				local renderInfo = 
						NmbDocValueToRenderInfo.extractRenderInfoFromDocValue(
							docValue )

				rxTest:logf( "Checking renderInfo.hasMasks hasMasks = %s  noMaskLinks = %s and noLocalMasks = %s",
								hasMasksValue, noMaskLinksValue,
								noLocalMasksValue )

				rxTest:expectEqual( hasMasksValue, renderInfo.hasDevelopAuxFiles )

				rxTest:logf( "Checking renderInfo.haveAllLocalAuxPathsInDocstore (%s) hasMasks = %s  noMaskLinks = %s and noLocalMasks = %s",
								renderInfo.haveAllLocalAuxPathsInDocstore,
								hasMasksValue, noMaskLinksValue,
								noLocalMasksValue )

				rxTest
					:expectEqual( 
						( hasMasksValue and not noLocalMasksValue ) or 
						( hasMasksValue and noMaskLinksValue ) or
						nil, 
						renderInfo.haveAllLocalAuxPathsInDocstore )

				rxTest:logf( "Checking renderInfo.externalDevelopFiles hasMasks = %s  noMaskLinks = %s and noLocalMasks = %s",
								hasMasksValue, noMaskLinksValue,
								noLocalMasksValue )

				local externalDevelopFiles = renderInfo.externalDevelopFiles or {}

				rxTest:expectEqual( #externalDevelopFiles, hasMasksValue and 3 or 1 )

				rxTest:logf( "Checking externalDevelopFiles has digest and/or href for all masks hasMasks = %s  noMaskLinks = %s and noLocalMasks = %s",
								hasMasksValue, noMaskLinksValue,
								noLocalMasksValue )

				for _, externalDevelopFileInfo in pairs( externalDevelopFiles ) do

					local fileType, _, uri = unpack( externalDevelopFileInfo )

					rxTest:expectEqual( true, fileType == "develop" or fileType == "aux" )

					rxTest:expectEqual( fileType == "develop" or not noMaskLinksValue, 
											type( uri ) == "string" )

				end

			end

		end

	end

end

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

local function rxTestExternalFilters( rxTest )

	local wfCatalog = WFCatMockCatalog.createFakeWFCatalog( rxTest )

	for _, hasFiltersValue in pairs( { true, false } ) do
		for _, noFilterLinksValue in pairs( { true, false } ) do
			for _, noLocalFiltersValue in pairs( { true, false } ) do

				local optArguments = {}

				if hasFiltersValue then

					optArguments.hasFilters = true

				end

				if noFilterLinksValue then

					optArguments.noFilterLinks = true

				end

				if noLocalFiltersValue then

					optArguments.noLocalFilters = true

				end

				local docValue = require "WFCatAssetTestUtils".createAssetDocument(
									rxTest, wfCatalog, nil, optArguments )

				local renderInfo =
						NmbDocValueToRenderInfo.extractRenderInfoFromDocValue(
							docValue )

				rxTest:logf( "Checking renderInfo.hasFilters hasFilters = %s  noFilterLinks = %s and noLocalFilters = %s",
								hasFiltersValue, noFilterLinksValue,
								noLocalFiltersValue )

				rxTest:expectEqual( hasFiltersValue, renderInfo.hasDevelopAuxFiles )

				rxTest:logf( "Checking renderInfo.haveAllLocalAuxPathsInDocstore (%s) hasFilters = %s  noFilterLinks = %s and noLocalFilters = %s",
								renderInfo.haveAllLocalAuxPathsInDocstore,
								hasFiltersValue, noFilterLinksValue,
								noLocalFiltersValue )

				rxTest
					:expectEqual(
						( hasFiltersValue and not noLocalFiltersValue ) or
						( hasFiltersValue and noFilterLinksValue ) or
						nil,
						renderInfo.haveAllLocalAuxPathsInDocstore )

				rxTest:logf( "Checking renderInfo.externalDevelopFiles hasFilters = %s  noFilterLinks = %s and noLocalFilters = %s",
								hasFiltersValue, noFilterLinksValue,
								noLocalFiltersValue )

				local externalDevelopFiles = renderInfo.externalDevelopFiles or {}

				-- Only the longest edge aux is loaded from the filter group
				rxTest:expectEqual( #externalDevelopFiles, hasFiltersValue and 2 or 1 )

				rxTest:logf( "Checking externalDevelopFiles has digest and/or href for all Filters hasFilters = %s  noFilterLinks = %s and noLocalFilters = %s",
								hasFiltersValue, noFilterLinksValue,
								noLocalFiltersValue )

				for _, externalDevelopFileInfo in pairs( externalDevelopFiles ) do

					local fileType, _, uri = unpack( externalDevelopFileInfo )

					rxTest:expectEqual( true, fileType == "develop" or fileType == "aux" )

					rxTest:expectEqual( fileType == "develop" or not noFilterLinksValue,
											type( uri ) == "string" )

				end

			end

		end

	end

end

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

local function rxTestOzOriginalLinks( rxTest )

	local wfCatalog = WFCatMockCatalog.createFakeWFCatalog( rxTest )

	for _, corruptMaster in ipairs( { false, true } ) do
	
		for _, masterLinkState in ipairs( { 'none', 'valid', 'invalid' } ) do

			for _, localOnlyError in ipairs( { false, 'binaryUploadErrors', 'binaryDownloadErrors' } ) do

				local docValue = 
					require "WFCatAssetTestUtils".createAssetDocument( 
					rxTest, wfCatalog, nil, 
					{

						corruptMaster = corruptMaster or nil,

						noMasterLink = masterLinkState == 'none' or nil,

						ozOriginalIsInvalid = masterLinkState == 'invalid' or nil,

					} )

				if localOnlyError then

					KSTableUtils.setNested( docValue, {}, '_localOnly', localOnlyError, '/rels/master' )

					local maybeOzOriginalLink = KSTableUtils.derefOpt( docValue, '_serverProvidedMetadata', 'links', '/rels/master', 'href' )

					if maybeOzOriginalLink then

						KSTableUtils.setNested( docValue, true, '_localOnly', localOnlyError, '/rels/master', maybeOzOriginalLink )

					end

				end

				rxTest:logf( "testing corruptMaster == %s, masterLinkState == %s, localOnlyError == %s",
								corruptMaster, masterLinkState, localOnlyError )

				local renderInfo =
						NmbDocValueToRenderInfo.extractRenderInfoFromDocValue( docValue )

				rxTest:expectEqual( 
					renderInfo.ozValidOriginalLink ~= nil, 
					not corruptMaster and masterLinkState == 'valid' and not localOnlyError )

				rxTest:expectEqual( 
						( masterLinkState == 'valid' and corruptMaster and localOnlyError == false ) or
						( masterLinkState == 'invalid' and localOnlyError == false ),
					renderInfo.ozInvalidOriginalLink ~= nil )

			end

		end

	end

end

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

return WFRxTestCase.wrapSuite( 'NmbDocValueToRenderInfoTest', {

	rxTestDisallowLocalEditsForDocValue = WFPlatformInfo.isDesktop and rxTestDisallowLocalEditsForDocValue or nil,

	rxTestExternalMasks = rxTestExternalMasks,

	rxTestExternalFilters = rxTestExternalFilters,

	rxTestOzOriginalLinks = rxTestOzOriginalLinks,

} )
