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

NmbLocalRenditionDigestTest.lua

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

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

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

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

	-- WF.core.utils
local WFTableMerge = require "WFTableMerge"
local KSIdGenerator = require 'KSIdGenerator'

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

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

local originalPath = 'path/to/original.jpg'
	
local proxyPath = 'path/to/proxy.jpg'
		
local sha256 = KSIdGenerator.uuidInLowercaseHex()

local localOriginalSha256 = sha256

local localProxySha256 = sha256

local function simplifiedDocValue()

	return {

		originalPath = originalPath,
		proxyPath = proxyPath,
		sha256 = sha256,
		localOriginalSha256 = localOriginalSha256,
		localProxySha256 = localProxySha256,
	}
	
end

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

local function rxTestSha256Changes( rxTest )

	local docValue = simplifiedDocValue( 'original' )
	
	local baselineDigest = NmbLocalRenditionDigest.computeFromRenderInfo( docValue )
	
	rxTest:expectEqual( NmbLocalRenditionDigest.computeFromRenderInfo( docValue ), baselineDigest )

	-- Changing the SHA256 of the doc should NOT cause digest to change, since the
	-- SHA256 of the original hasn't changed ( and we always prefer to render
	-- using the original ).

	docValue.sha256 = KSIdGenerator.uuidInLowercaseHex()

	rxTest:expectEqual( NmbLocalRenditionDigest.computeFromRenderInfo( docValue ), baselineDigest )
	
	-- Changing SHA256 of the original asset should force the digest to change.
	
	docValue.localOriginalSha256 = KSIdGenerator.uuidInLowercaseHex()

	rxTest:expectNotEqual( NmbLocalRenditionDigest.computeFromRenderInfo( docValue ), baselineDigest )
	
	-- Removing the Original should NOT cause the digest to change, since it has the same
	-- SHA256 as the original.

	docValue.localOriginalSha256 = nil

	rxTest:expectEqual( NmbLocalRenditionDigest.computeFromRenderInfo( docValue ), baselineDigest )

	-- Downloading an original should NOT cause the digest to change if it has the
	-- same SHA256 as the proxy.
	
	docValue.localOriginalSha256 = docValue.localProxySha256

	rxTest:expectEqual( NmbLocalRenditionDigest.computeFromRenderInfo( docValue ), baselineDigest )
	
	-- Removing original and proxy, and changing SHA of the doc should cause the asset
	-- digest to change.
	
	docValue.localOriginalSha256 = nil
	docValue.localProxySha256 = nil
	docValue.sha256 = KSIdGenerator.uuidInLowercaseHex()
	
	rxTest:expectNotEqual( NmbLocalRenditionDigest.computeFromRenderInfo( docValue ), baselineDigest )

	-- Downloading a new proxy with a new SHA should cause the digest to change.
	
	docValue.localProxySha256 = KSIdGenerator.uuidInLowercaseHex()
	
	rxTest:expectNotEqual( NmbLocalRenditionDigest.computeFromRenderInfo( docValue ), baselineDigest )

	----------------------------------------------------------------------------
	
	-- Start with a freshly imported image
	
	local importedDocValue = simplifiedDocValue( 'original' )
	importedDocValue.localProxySha256 = nil
	importedDocValue.proxyPath = nil
	importedDocValue.firstOzRevisionId = nil
	importedDocValue.ozMasterLink = nil
	importedDocValue.ozProxyLink = nil

	baselineDigest = NmbLocalRenditionDigest.computeFromRenderInfo( importedDocValue )
	
	-- Uploading the asset to Oz should not cause the digest to change.
	
	importedDocValue.localProxySha256 = localProxySha256
	importedDocValue.proxyPath = proxyPath
	
	rxTest:expectEqual( NmbLocalRenditionDigest.computeFromRenderInfo( importedDocValue ), baselineDigest )
	
end

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

local _xmpCameraRaw = [[
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.6-c140 79.160451, 2017/05/06-01:08:21 "> 
<rdf:RDF xmlns:rdf="/www.w3.org/1999/02/22-rdf-syntax-ns#"> 
<rdf:Description rdf:about="" xmlns:crs="/ns.adobe.com/camera-raw-settings/1.0/" 
crs:Version="11.2" 
crs:ProcessVersion="6.7" 
crs:WhiteBalance="As Shot" 
crs:Temperature="2000" 
crs:Tint="-150" 
crs:Saturation="0" 
crs:Sharpness="58" 
crs:LuminanceSmoothing="23" 
crs:ColorNoiseReduction="25" 
crs:VignetteAmount="0" 
crs:ShadowTint="0" 
crs:RedHue="0" 
crs:RedSaturation="0" 
crs:GreenHue="0" 
crs:GreenSaturation="0" 
crs:BlueHue="0" 
crs:BlueSaturation="0" 
crs:Vibrance="0" 
crs:HueAdjustmentRed="0" 
crs:HueAdjustmentOrange="0" 
crs:HueAdjustmentYellow="0" 
crs:HueAdjustmentGreen="0" 
crs:HueAdjustmentAqua="0"
crs:HueAdjustmentBlue="0"
crs:HueAdjustmentPurple="0"
crs:HueAdjustmentMagenta="0"
crs:SaturationAdjustmentRed="0"
crs:SaturationAdjustmentOrange="0"
crs:SaturationAdjustmentYellow="0"
crs:SaturationAdjustmentGreen="0"
crs:SaturationAdjustmentAqua="0"
crs:SaturationAdjustmentBlue="0"
crs:SaturationAdjustmentPurple="0"
crs:SaturationAdjustmentMagenta="0"
crs:LuminanceAdjustmentRed="0"
crs:LuminanceAdjustmentOrange="0"
crs:LuminanceAdjustmentYellow="0"
crs:LuminanceAdjustmentGreen="0"
crs:LuminanceAdjustmentAqua="0"
crs:LuminanceAdjustmentBlue="0"
crs:LuminanceAdjustmentPurple="0"
crs:LuminanceAdjustmentMagenta="0"
crs:SplitToningShadowHue="0"
crs:SplitToningShadowSaturation="0"
crs:SplitToningHighlightHue="52"
crs:SplitToningHighlightSaturation="64"
crs:SplitToningBalance="0"
crs:ParametricShadows="0"
crs:ParametricDarks="0"
crs:ParametricLights="0"
crs:ParametricHighlights="0"
crs:ParametricShadowSplit="25"
crs:ParametricMidtoneSplit="50"
crs:ParametricHighlightSplit="75"
crs:SharpenRadius="+1.0"
crs:SharpenDetail="25"
crs:SharpenEdgeMasking="53"
crs:PostCropVignetteAmount="0"
crs:GrainAmount="0"
crs:LuminanceNoiseReductionDetail="50"
crs:ColorNoiseReductionDetail="50"
crs:LuminanceNoiseReductionContrast="0"
crs:ColorNoiseReductionSmoothness="50" 
crs:LensProfileEnable="1"
crs:LensManualDistortionAmount="0"
crs:PerspectiveVertical="0"
crs:PerspectiveHorizontal="0"
crs:PerspectiveRotate="0.0"
crs:PerspectiveScale="100"
crs:PerspectiveAspect="0"
crs:PerspectiveUpright="0"
crs:PerspectiveX="0.00"
crs:PerspectiveY="0.00"
crs:AutoLateralCA="1"
crs:Exposure2012="0.00"
crs:Contrast2012="0"
crs:Highlights2012="0"
crs:Shadows2012="0"
crs:Whites2012="0"
crs:Blacks2012="0"
crs:Clarity2012="0"
crs:DefringePurpleAmount="0"
crs:DefringePurpleHueLo="30"
crs:DefringePurpleHueHi="70"
crs:DefringeGreenAmount="0"
crs:DefringeGreenHueLo="40"
crs:DefringeGreenHueHi="60"
crs:Dehaze="0"
crs:ToneMapStrength="0"
crs:ConvertToGrayscale="False"
crs:OverrideLookVignette="False"
crs:ToneCurveName="Medium Contrast"
crs:ToneCurveName2012="Linear"
crs:CameraProfile="Adobe Standard"
crs:CameraProfileDigest="944968722A058A1EADE7D6E3922A771B"
crs:LensProfileSetup="LensDefaults"
crs:UprightVersion="151388160"
crs:UprightCenterMode="0"
crs:UprightCenterNormX="0.5"
crs:UprightCenterNormY="0.5"
crs:UprightFocalMode="0"
crs:UprightFocalLength35mm="35"
crs:UprightPreview="False"
crs:UprightTransformCount="6"
crs:UprightFourSegmentsCount="0"
crs:HasSettings="True"
crs:AlreadyApplied="False">
<crs:ToneCurve>
<rdf:Seq>
<rdf:li>0, 0</rdf:li>
<rdf:li>32, 22</rdf:li>
<rdf:li>64, 56</rdf:li>
<rdf:li>128, 128</rdf:li>
<rdf:li>192, 196</rdf:li>
<rdf:li>255, 255</rdf:li>
</rdf:Seq>
</crs:ToneCurve>
<crs:ToneCurveRed>
<rdf:Seq>
<rdf:li>0, 0</rdf:li>
<rdf:li>255, 255</rdf:li>
</rdf:Seq>
</crs:ToneCurveRed>
<crs:ToneCurveGreen>
<rdf:Seq>
<rdf:li>0, 0</rdf:li>
<rdf:li>255, 255</rdf:li>
</rdf:Seq>
</crs:ToneCurveGreen>
<crs:ToneCurveBlue>
<rdf:Seq>
<rdf:li>0, 0</rdf:li>
<rdf:li>255, 255</rdf:li>
</rdf:Seq>
</crs:ToneCurveBlue>
<crs:ToneCurvePV2012>
<rdf:Seq>
<rdf:li>0, 0</rdf:li>
<rdf:li>255, 255</rdf:li>
</rdf:Seq>
</crs:ToneCurvePV2012>
<crs:ToneCurvePV2012Red>
<rdf:Seq>
<rdf:li>0, 0</rdf:li>
<rdf:li>255, 255</rdf:li>
</rdf:Seq>
</crs:ToneCurvePV2012Red>
<crs:ToneCurvePV2012Green>
<rdf:Seq>
<rdf:li>0, 0</rdf:li>
<rdf:li>255, 255</rdf:li>
</rdf:Seq>
</crs:ToneCurvePV2012Green>
<crs:ToneCurvePV2012Blue>
<rdf:Seq>
<rdf:li>0, 0</rdf:li>
<rdf:li>255, 255</rdf:li>
</rdf:Seq>
</crs:ToneCurvePV2012Blue>
<crs:Look
crs:Name=""/>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta> ]]

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

local function mergeAll( ... )

	local ret = {}

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

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

	end

	return ret

end

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

local function rxTestIsUniqueEmptySettingsForDownloadOnlyAsset( rxTest )

	local notUniqueEmpty = {

		NmbLocalRenditionDigest.privateUnitTestExports.makeUniqueEmptySettingsForDownloadOnlyAssetImp( 
			"This string is 32 characters!!!" ),

		NmbLocalRenditionDigest.privateUnitTestExports.makeUniqueEmptySettingsForDownloadOnlyAssetImp( 
			"nah" ),

		-- this has uuid chars, but not enough
		NmbLocalRenditionDigest.privateUnitTestExports.makeUniqueEmptySettingsForDownloadOnlyAssetImp( 
			"abcedf1234567890" ),


		NmbLocalRenditionDigest.privateUnitTestExports.makeUniqueEmptySettingsForDownloadOnlyAssetImp( 
			"" ),

		"<xmp/>",

		"<xmp></xmp>",

		{},

		_xmpCameraRaw,

	}

	for _, xmp in pairs( notUniqueEmpty ) do

		rxTest:expectEqual(
			NmbLocalRenditionDigest.isUniqueEmptySettingsForDownloadOnlyAsset( xmp ),
			false )

	end

	local uniqueEmpty = 
		NmbLocalRenditionDigest.privateUnitTestExports.makeUniqueEmptySettingsForDownloadOnlyAssetImp( 
			KSIdGenerator.uuidInLowercaseHex() )

	rxTest:expectEqual(
		true,
		NmbLocalRenditionDigest.isUniqueEmptySettingsForDownloadOnlyAsset( uniqueEmpty ) )
	
end

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

local function rxTestDigestForInvalidRenditionDownloads( rxTest )

	local revId = 'd5d3c23ab040483eaf89e8bd8eadd8da'

	local serverProvidedValidRenditions =
			{
				_serverProvidedMetadata = {
					revision_ids = {
						revId
					},
					links = {
						[ '/rels/rendition_type/640' ] = {
							href = "/fakeyVonFakenste.in/notreal.jpg"
						}
					}
				}
			}

	local serverProvidedInvalidRenditions =
			{
				_serverProvidedMetadata = {
					links = {
						[ '/rels/rendition_type/1280' ] = {
							href = "/fakeyVonFakenste.in/Invalidnotreal.jpg",
							invalid = true
						}
					}
				}
			}

	local serverProvidedMasterDownloadLink =
			{
				_serverProvidedMetadata = {
					links = {
						[ '/rels/master' ] = {
							href = "/fakeyVonFakenste.in/master.jpg",
						}
					}
				}
			}

	local serverProvidedProxyDownloadLink =
			{
				_serverProvidedMetadata = {
					links = {
						[ '/rels/proxy_type/2560' ] = {
							href = "/fakeyVonFakenste.in/proxy.jpg",
						}
					}
				}
			}

	local defaultAdjustments = 
		{
			develop = {
				xmpCameraRaw = '<xmp />',
			}
		}

	local embeddedAdjustments = 
		{
			develop = {
				xmpCameraRaw = _xmpCameraRaw,
			}
		}

	local externalAdjustments = 
		{
			_serverProvidedMetadata = {
				links = {
					[ '/rels/xmp/develop' ] = {
						href = "/fakeyVonFakenste.in/develop.xmp",
					}
				}
			},
			develop = {
				xmpCameraRaw = {
					sha256 = "99b1dd7ad29e57b7c016aab7390997fb70c0b767112f9075aec7910facfc29de"
				}
			}
		}

	local baseDocValue =
			{
				_id = 'doc_1',
				_revId=revId,
				subtype = 'image',
				develop = {
					croppedHeight = 150,
					croppedWidth = 150,
					userOrientation = 4,
				},
				rating = 3,
			}

	for _, hasServerProxy in ipairs( { true, false } ) do
		for _, hasServerOrig in ipairs( { true, false } ) do
			for _, hasServerRenditions in ipairs( { true, false } ) do
				for _, isSharedAlbum in ipairs( { true, false } ) do
					for _, settingsType in ipairs( { 'none', 'default', 'embedded', 'external' } ) do

						local extraDocValueData = {}

						if hasServerProxy then

							extraDocValueData[ #extraDocValueData + 1 ] = serverProvidedProxyDownloadLink

						end

						if hasServerOrig then

							extraDocValueData[ #extraDocValueData + 1 ] = serverProvidedMasterDownloadLink

						end

						if hasServerRenditions then

							extraDocValueData[ #extraDocValueData + 1 ] = serverProvidedValidRenditions

						end

						if settingsType == 'default' then

							extraDocValueData[ #extraDocValueData + 1 ] = defaultAdjustments

						elseif settingsType == 'embedded' then

							extraDocValueData[ #extraDocValueData + 1 ] = embeddedAdjustments

						elseif settingsType == 'external' then

							extraDocValueData[ #extraDocValueData + 1 ] = externalAdjustments 

						end

						local docValue = mergeAll( baseDocValue, unpack( extraDocValueData ) )

						if isSharedAlbum then

							docValue._spaceId = "yass"

						end

						local docValueWithInvalidRenditions = mergeAll( docValue, serverProvidedInvalidRenditions )

						local digestForValidRendition =
								NmbLocalRenditionDigest.maybeComputeFromDocValue( docValue )

						local digestForInvalidRendition =
								NmbLocalRenditionDigest.maybeComputeFromDocValue( docValueWithInvalidRenditions )

						local expectingDifferentDigests =
								not( hasServerProxy or hasServerOrig or hasServerRenditions )

						rxTest:logf( "Checking if digests are %s when hasServerProxy %s, hasServerOrig %s, hasServerRenditions %s, isSharedAlbum %s, settingsType %s,",
										expectingDifferentDigests and "different" or "same",
										hasServerProxy, hasServerOrig, hasServerRenditions, isSharedAlbum, settingsType )
						
						if expectingDifferentDigests then

							rxTest:expectNotEqual( digestForValidRendition, digestForInvalidRendition )

						else

							rxTest:expectEqual( digestForValidRendition, digestForInvalidRendition )

						end

					end
				end
			end
		end
	end

end

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


return WFRxTestCase.wrapSuite( {

	rxTestSha256Changes = rxTestSha256Changes,

	rxTestIsUniqueEmptySettingsForDownloadOnlyAsset = 
		rxTestIsUniqueEmptySettingsForDownloadOnlyAsset,

	rxTestDigestForInvalidRenditionDownloads =
		rxTestDigestForInvalidRenditionDownloads,

} )
