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

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

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

	-- LrmModels
local LrmAssetUtils = require 'LrmAssetUtils'

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

	-- WF.core.os
local WFDeviceInfo = require 'WFDeviceInfo'

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

	-- WF.oz_client.catalog
local WFOzContentTypes = require 'WFOzContentTypes'


	-- WF.oz_client.managed_catalog
local WFCatAssetTestUtils = require 'WFCatAssetTestUtils'
local WFCatMockCatalog = require 'WFCatMockCatalog'

local LrmCatalogTestHelper

if WFPlatformInfo.isMobile() then
	LrmCatalogTestHelper = require 'LrmCatalogTestHelper'
end

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

local LrmAssetUtilsTest = {}

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

function LrmAssetUtilsTest.rxTestGetLocalUrl( rxTest )

	local docValue = {
		_localOnly = {
			localUrl = '1234',
		},
	}
	
	local deviceId = WFDeviceInfo.uniqueDeviceId()
	local deviceId2 = KSIdGenerator.uuidInLowercaseHex()
	
	local getUrl = LrmAssetUtils.getLocalUrl
	
	rxTest:makeVerbose()
	
	rxTest:expectEqual( getUrl( docValue ), '1234' )
	
	WFTableMerge.applyOverlay( docValue, {
		_localOnly = {
			localUrl = { _delete = true },
		},
		importSource = {
			uniqueDeviceId = deviceId,
			localAssetId = '1234',
		}
	} )
	
	rxTest:expectEqual( getUrl( docValue ), '1234' )
	
	
	WFTableMerge.applyOverlay( docValue, {
		importSource = {
			uniqueDeviceId = deviceId2,
		}
	} )
	
	rxTest:expectEqual( getUrl( docValue ), nil )
	
	WFTableMerge.applyOverlay( docValue, {
		_localOnly = {
			localUrl = '1234',
		},
		importSource = {
			uniqueDeviceId = deviceId,
			localAssetId = '5678',
		}
	} )
	
	rxTest:expectEqual( getUrl( docValue ), '1234' )
	
end

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

local function createFakeWFCatalog( rxTest )

	if WFPlatformInfo.isAndroid then
	
		local _, wfCatalog = LrmCatalogTestHelper.makeCatalogService()
		return wfCatalog

	else

		local optArgs = {}
			
		if WFPlatformInfo.isiOS then
			optArgs.indexDefinitions = 'LrmCatalogIndexDefinitions.lua'
		end

		return WFCatMockCatalog.createFakeWFCatalog( rxTest , nil, nil, optArgs )

	end

end

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

local function createAssetDoc( rxTest, wfCatalog, overrides )

	local assetId = KSIdGenerator.uuidInLowercaseHex()
	
	return WFCatAssetTestUtils.createAssetDocument( rxTest, wfCatalog, assetId, overrides )

end

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

function LrmAssetUtilsTest.rxTestHasProxyOnOz( rxTest )

	local wfCatalog = createFakeWFCatalog( rxTest )
	
	-- Image (Default)
	
	local overrides = {}
	
	local docValue = createAssetDoc( rxTest, wfCatalog, overrides )
	
	local result = LrmAssetUtils.hasProxyOnOz( docValue )
		
	rxTest:expectEqual( true, result )
			
	-- Image (2560)
	
	overrides = {}
	
	docValue = createAssetDoc( rxTest, wfCatalog, overrides )
	
	result = LrmAssetUtils.hasProxyOnOz( docValue, '2560' )
	
	rxTest:expectEqual( true, result )
				
	-- Image (Panorama)
	
	overrides = {
		isPanorama = true
	}
	
	docValue = createAssetDoc( rxTest, wfCatalog, overrides )
	
	result = LrmAssetUtils.hasProxyOnOz( docValue, 'panorama' )
	
	rxTest:expectEqual( true, result )
	
	-- Image (Fullsize)
	
	overrides = {}
	
	docValue = createAssetDoc( rxTest, wfCatalog, overrides )
	
	result = LrmAssetUtils.hasProxyOnOz( docValue, 'fullsize' )
	
	rxTest:expectEqual( true, result )
	
	-- No Proxy Links
	
	overrides = {
		noProxyLink = true
	}
	
	docValue = createAssetDoc( rxTest, wfCatalog, overrides )
	
	result = LrmAssetUtils.hasProxyOnOz( docValue )
	
	rxTest:expectEqual( false, result )
	
	-- Video (Default)
	
	overrides = {
		docSubtype = 'video'
	}
	
	docValue = createAssetDoc( rxTest, wfCatalog, overrides )
	
	result = LrmAssetUtils.hasProxyOnOz( docValue )
	
	rxTest:expectEqual( true, result )
	
	-- Video (1080p)
	
	overrides = {
		docSubtype = 'video'
	}
	
	docValue = createAssetDoc( rxTest, wfCatalog, overrides )
	
	result = LrmAssetUtils.hasProxyOnOz( docValue, '1080p' )
	
	rxTest:expectEqual( true, result )
	
	-- Video (360p)
	
	overrides = {
		docSubtype = 'video'
	}
	
	docValue = createAssetDoc( rxTest, wfCatalog, overrides )
	
	result = LrmAssetUtils.hasProxyOnOz( docValue, '360p' )
	
	rxTest:expectEqual( true, result )
	
	-- Video, No Proxy Links
	
	overrides = {
		docSubtype = 'video',
		noProxyLink = true
	}
	
	docValue = createAssetDoc( rxTest, wfCatalog, overrides )
	
	result = LrmAssetUtils.hasProxyOnOz( docValue )
	
	rxTest:expectEqual( false, result )
	
end

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

local function makeProxyDocValue()

	local docValue

	if WFPlatformInfo.isiOS then
		docValue = {
			_localOnly = {
				files = {
					proxy = {
						path = '/var/mobile/...'
					}
				}
			}
		}
	else
		docValue = {
			_localOnly = {
				proxy = {
					filePath = '/var/mobile/...'
				}
			}
		}
	end

	return docValue

end

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

local function makeOriginalDocValue()

	local docValue

	if WFPlatformInfo.isiOS then
		docValue = {
			_localOnly = {
				files = {
					master = {
						path = '/var/mobile/...'
					}
				}
			}
		}
	else
		docValue = {
			_localOnly = {
				originalFilePath = '/var/mobile/...'
			}
		}
	end

	return docValue

end

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

local function makeLatestOriginalDocValue()

	local docValue

	if WFPlatformInfo.isiOS then
		docValue = {
			_localOnly = {
				files = {
					latestMaster = {
						path = '/var/mobile/...'
					}
				}
			}
		}
	else
		docValue = {
		_localOnly = {
			latestOriginal = {
				filePath = '/var/mobile/...'
			}
		}
	}
	
	end

	return docValue

end

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

local function makeOriginalAndProxyDocValue()

	local docValue

	if WFPlatformInfo.isiOS then
		docValue = {
			_localOnly = {
				files = {
					master = {
						path = 'Originals/...'
					},
					proxy = {
						path = '/proxy'
					}
				}
			}
		}
	else
		docValue = {
			_localOnly = {
				originalFilePath = '/var/mobile/...',
				proxy = {
					filePath = '/proxy'
				}
			}
		}
	end

	return docValue

end

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

local function makePreviewDocValue()

	local docValue

	if WFPlatformInfo.isiOS then
		docValue = {
			_localOnly = {
				files = {
					preview = {}
				}
			}
		}
	else
		docValue = {
			_localOnly = {
				preview = {}
			}
		}
	end

	return docValue

end

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

local function removeOriginalFilePathFromDocValue( docValue )

	if WFPlatformInfo.isiOS then
		docValue._localOnly.files.master.path = nil
	else
		docValue._localOnly.originalFilePath = nil
	end

	return docValue
end

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

local function removeLatestOriginalFilePathFromDocValue( docValue )

	if WFPlatformInfo.isiOS then
		docValue._localOnly.files.latestMaster.path = nil
	else
		docValue._localOnly.latestOriginal.filePath = nil
	end

	return docValue
end
--------------------------------------------------------------------------------

local function removePreviewFromDocValue( docValue )

	if WFPlatformInfo.isiOS then
		docValue._localOnly.files.preview = nil
	else
		docValue._localOnly.preview = nil
	end

	return docValue
end

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

function LrmAssetUtilsTest.rxTestHasProxyLocally( rxTest )

	local wfCatalog = createFakeWFCatalog( rxTest )
	
	-- Image (Default)
	
	local overrides = {}
	
	local docValue = createAssetDoc( rxTest, wfCatalog, overrides )
	
	local result = LrmAssetUtils.hasProxyLocally( docValue )
				
	rxTest:expectEqual( true, result )
				
	-- Image (2560)
	
	overrides = {
		hasLocal2560Proxy = true
	}
	
	docValue = createAssetDoc( rxTest, wfCatalog, overrides )
	
	result = LrmAssetUtils.hasProxyLocally( docValue, '2560' )

	rxTest:expectEqual( true, result )

	-- No Local Proxy
	
	overrides = {
		noLocalProxy = true
	}
	
	docValue = createAssetDoc( rxTest, wfCatalog, overrides )
	
	result = LrmAssetUtils.hasProxyLocally( docValue )
	
	rxTest:expectEqual( false, result )
	
	-- Video (Default)
	
	overrides = {
		docSubtype = 'video'
	}
	
	docValue = createAssetDoc( rxTest, wfCatalog, overrides )
	
	result = LrmAssetUtils.hasProxyLocally( docValue )
	
	rxTest:expectEqual( true, result )
	
	-- Video (1080p)
	
	overrides = {
		docSubtype = 'video',
		hasLocal1080p = true
	}
	
	docValue = createAssetDoc( rxTest, wfCatalog, overrides )
	
	result = LrmAssetUtils.hasProxyLocally( docValue, '1080p' )
	
	rxTest:expectEqual( true, result )
	
	-- Video (360p)
	
	overrides = {
		docSubtype = 'video',
		hasLocal360p = true
	}
	
	docValue = createAssetDoc( rxTest, wfCatalog, overrides )
	
	result = LrmAssetUtils.hasProxyLocally( docValue, '360p' )
	
	rxTest:expectEqual( true, result )
	
	-- Video, No Local Proxy
	
	overrides = {
		docSubtype = 'video',
		noLocalProxy = true
	}
	
	docValue = createAssetDoc( rxTest, wfCatalog, overrides )
	
	result = LrmAssetUtils.hasProxyLocally( docValue )
	
	rxTest:expectEqual( false, result )

end

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

function LrmAssetUtilsTest.rxTestGetProxyPath( rxTest )

	local wfCatalog = createFakeWFCatalog( rxTest )
	
	-- Image (Default)
	
	local overrides = {}
	
	local docValue, expectedData = createAssetDoc( rxTest, wfCatalog, overrides )
	
	local result = LrmAssetUtils.getProxyPath( docValue )
				
	rxTest:expectEqual( expectedData.proxyFilePath, result )
				
	-- Image (2560)
	
	overrides = {
		hasLocal2560Proxy = true
	}
	
	docValue, expectedData = createAssetDoc( rxTest, wfCatalog, overrides )
	
	result = LrmAssetUtils.getProxyPath( docValue, '2560' )

	rxTest:expectEqual( expectedData.proxyFilePath, result )

	-- No Local Proxy
	
	overrides = {
		noLocalProxy = true
	}
	
	docValue, expectedData = createAssetDoc( rxTest, wfCatalog, overrides )
	
	result = LrmAssetUtils.getProxyPath( docValue )
	
	rxTest:expectEqual( nil, result )
	
	-- Video (Default)
	
	overrides = {
		docSubtype = 'video'
	}
	
	docValue, expectedData = createAssetDoc( rxTest, wfCatalog, overrides )
	
	result = LrmAssetUtils.getProxyPath( docValue )
	
	rxTest:expectEqual( expectedData.proxy1080pFilePath, result )
	
	-- Video (1080p)
	
	overrides = {
		docSubtype = 'video',
		hasLocal1080p = true
	}
	
	docValue, expectedData = createAssetDoc( rxTest, wfCatalog, overrides )
	
	result = LrmAssetUtils.getProxyPath( docValue, '1080p' )
	
	rxTest:expectEqual( expectedData.proxy1080pFilePath, result )
	
	-- Video (360p)
	
	overrides = {
		docSubtype = 'video',
		hasLocal360p = true
	}
	
	docValue, expectedData = createAssetDoc( rxTest, wfCatalog, overrides )
	
	result = LrmAssetUtils.getProxyPath( docValue, '360p' )
	
	rxTest:expectEqual( expectedData.proxy360pFilePath, result )
	
	-- Video, No Local Proxy
	
	overrides = {
		docSubtype = 'video',
		noLocalProxy = true
	}
	
	docValue, expectedData = createAssetDoc( rxTest, wfCatalog, overrides )
	
	result = LrmAssetUtils.getProxyPath( docValue )
	
	rxTest:expectEqual( nil, result )

end

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

function LrmAssetUtilsTest.rxTestHasProxy( rxTest )

	local docValue = makeProxyDocValue()

	docValue._serverProvidedMetadata = {
		links = {
			[ '/rels/proxy_type/2560' ] = {
				href = '/v1.0/123/revisions/123/proxy',
			}
		}
	}
	
	rxTest:expectEqual( LrmAssetUtils.hasProxy( docValue ), true )
	
	docValue[ '_serverProvidedMetadata' ] = nil
	
	rxTest:expectEqual( LrmAssetUtils.hasProxy( docValue ), true )
	
	docValue[ '_localOnly' ] = nil
	
	rxTest:expectEqual( LrmAssetUtils.hasProxy( docValue ), false )
	
end

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

function LrmAssetUtilsTest.rxTestHasMasterOnOz( rxTest )

	local docValue = {
		_serverProvidedMetadata = {
			links = {
				[ '/rels/master' ] = {
					href = '/v1.0/123/revisions/123/proxy',
				}
			}
		}
	}
	
	rxTest:expectEqual( LrmAssetUtils.hasMasterOnOz( docValue ), true )
	
	docValue._serverProvidedMetadata.links[ '/rels/master' ] = nil
	
	rxTest:expectEqual( LrmAssetUtils.hasMasterOnOz( docValue ), false )
	
end

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

function LrmAssetUtilsTest.rxTestHasMasterLocally( rxTest )

	local docValue = makeOriginalDocValue()

	rxTest:expectEqual( LrmAssetUtils.hasMasterLocally( docValue ), true )

	docValue = removeOriginalFilePathFromDocValue( docValue )

	rxTest:expectEqual( LrmAssetUtils.hasMasterLocally( docValue ), false )

	docValue = makeLatestOriginalDocValue()

	rxTest:expectEqual( LrmAssetUtils.hasMasterLocally( docValue ), true )
	
	docValue = removeLatestOriginalFilePathFromDocValue( docValue )
	
	rxTest:expectEqual( LrmAssetUtils.hasMasterLocally( docValue ), false )

end

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

function LrmAssetUtilsTest.rxTestHasMaster( rxTest )

	local docValue = makeOriginalDocValue()

	docValue._serverProvidedMetadata = {
		links = {
			[ '/rels/master' ] = {
				href = '/v1.0/123/revisions/123/proxy',
			}
		}
	}

	rxTest:expectEqual( LrmAssetUtils.hasMaster( docValue ), true )
	
	docValue._serverProvidedMetadata.links[ '/rels/master' ] = nil
	
	rxTest:expectEqual( LrmAssetUtils.hasMaster( docValue ), true )
	
	docValue = removeOriginalFilePathFromDocValue( docValue )
	
	rxTest:expectEqual( LrmAssetUtils.hasMaster( docValue ), false )
	
end

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

function LrmAssetUtilsTest.rxTestHasPreviewLocally( rxTest )

	local docValue = makePreviewDocValue()
	
	rxTest:expectEqual( LrmAssetUtils.hasPreviewLocally( docValue ), true )

	docValue = removePreviewFromDocValue( docValue )
	
	rxTest:expectEqual( LrmAssetUtils.hasPreviewLocally( docValue ), false )
	 
end

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

function LrmAssetUtilsTest.rxTestIsVideo( rxTest )

	local docValue = {
		type = 'asset',
		subtype = 'video',
	}
	
	rxTest:expectEqual( LrmAssetUtils.isVideo( docValue ), true )
	
	docValue.subtype = 'image'
	
	rxTest:expectEqual( LrmAssetUtils.isVideo( docValue ), false )
	
end

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

function LrmAssetUtilsTest.rxTestGetContentTypeNumber( rxTest )

	local imageTypeNumLo, imageTypeNumHi = WFOzContentTypes.getContentTypeNumberRangeForSubType "jpeg"
	
	local function verifyImageContentType( docValue )
		
		local contentTypeNumber = LrmAssetUtils.getContentTypeNumber( docValue )
	
		rxTest:expectEqual( contentTypeNumber >= imageTypeNumLo, true )
		rxTest:expectEqual(contentTypeNumber <= imageTypeNumHi, true )
		
	end
	
	local docValue = {
		importSource = {
			contentType = 'image/jpeg',
		}
	}
	
	verifyImageContentType( docValue )
	
	docValue.importSource.contentType = 'video/mp4'
	
	docValue = {
		_serverProvidedMetadata = {
			links = {
				[ '/rels/master' ] = {
					content_type = 'image/jpeg'
				}
			}
		}
	}
	
	verifyImageContentType( docValue )
	
	docValue = {
		_serverProvidedMetadata = {
			subtype = 'jpeg',
		}
	}
	
	verifyImageContentType( docValue )
	
	rxTest:expectEqual( LrmAssetUtils.getContentTypeNumber( nil ), 1000 )
	
end

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

function LrmAssetUtilsTest.rxTestIsVideoContentType( rxTest )

	local docValue = {
		importSource = {
			contentType = 'image/jpeg',
		}
	}
	
	local contentTypeNumber = LrmAssetUtils.getContentTypeNumber( docValue )
	
	rxTest:expectEqual( LrmAssetUtils.isVideoContentTypeNumber( contentTypeNumber ), false )
	
	docValue.importSource.contentType = 'video/mp4'
	
	contentTypeNumber = LrmAssetUtils.getContentTypeNumber( docValue )
	
	rxTest:expectEqual( LrmAssetUtils.isVideoContentTypeNumber( contentTypeNumber ), true )
	
	rxTest:expectEqual( LrmAssetUtils.isVideoContentTypeNumber( nil ), false )
	
end

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

-- test no longer valid on iOS (replaced with TIBlobProvider)

if not WFPlatformInfo.isiOS then

	function LrmAssetUtilsTest.rxTestGetRenditionRevision( rxTest )

		local docValue = {
			_localOnly = {
				thumbnail2x = {
					revId = 'foo',
				},
				preview = {
					revId = 'previewRevision',
				}
			},
		}
	
		rxTest:expectEqual( LrmAssetUtils.getRenditionRevision( docValue, 'thumbnail2x' ), 'foo' )
	
		rxTest:expectEqual( LrmAssetUtils.getRenditionRevision( docValue, 'preview' ), 'previewRevision' )
	
	end

end

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

function LrmAssetUtilsTest.rxTestGetLensProfileInfo( rxTest )

	local docValue = {
		develop = {
			profiles = {
				lens = {
					href = '/v1.0/catalogs/123',
					filename = 'Nikon Lens',
				},
			},
		},
	}
	
	local lensProfileInfo = LrmAssetUtils.getLensProfileInfo( docValue )
	
	rxTest:expectEqual( lensProfileInfo ~= nil, true )
	rxTest:expectEqual( lensProfileInfo.filename, 'Nikon Lens' )
	rxTest:expectEqual( lensProfileInfo.href, '/v1.0/catalogs/123' )
	
	docValue.develop.profiles.lens.href = 'Embedded'
	
	lensProfileInfo = LrmAssetUtils.getLensProfileInfo( docValue )
	rxTest:expectEqual( lensProfileInfo, nil )
	
	docValue.develop.profiles.lens.href = '/fo'
	docValue.develop.profiles.lens.filename = nil
	
	lensProfileInfo = LrmAssetUtils.getLensProfileInfo( docValue )
	rxTest:expectEqual( lensProfileInfo, nil )
	
end

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

function LrmAssetUtilsTest.rxTestGetCameraProfileInfo( rxTest )

	local docValue = {
		develop = {
			profiles = {
				camera = {
					href = '/v1.0/catalogs/123',
					filename = 'Nikon Camera',
				},
			},
		},
	}
	
	local cameraProfileInfo = LrmAssetUtils.getCameraProfileInfo( docValue )
	
	rxTest:expectEqual( cameraProfileInfo ~= nil, true )
	rxTest:expectEqual( cameraProfileInfo.filename, 'Nikon Camera' )
	rxTest:expectEqual( cameraProfileInfo.href, '/v1.0/catalogs/123' )
	
	docValue.develop.profiles.camera.href = 'Embedded'
	
	cameraProfileInfo = LrmAssetUtils.getCameraProfileInfo( docValue )
	rxTest:expectEqual( cameraProfileInfo, nil )
	
	docValue.develop.profiles.camera.href = '/fo'
	docValue.develop.profiles.camera.filename = nil
	
	cameraProfileInfo = LrmAssetUtils.getCameraProfileInfo( docValue )
	rxTest:expectEqual( cameraProfileInfo, nil )
	
end

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

-- test no longer valid on iOS (replaced with TIBlobProvider)

if not WFPlatformInfo.isiOS then

	function LrmAssetUtilsTest.rxTestIsDeveloped( rxTest )
	
		local docValue = {
			develop = {
				xmpCameraRaw = 'xmp',
			},
		}

		rxTest:expectEqual( LrmAssetUtils.isDeveloped( docValue ), true )
	
		docValue.develop.xmpCameraRaw = ''
	
		rxTest:expectEqual( LrmAssetUtils.isDeveloped( docValue ), false )
	
		docValue.develop.xmpCameraRaw = nil
	
		rxTest:expectEqual( LrmAssetUtils.isDeveloped( docValue ), false )

	end
	
end

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

function LrmAssetUtilsTest.rxTestGetDefaultAssetRating( rxTest )

	local userId = KSIdGenerator.uuidInLowercaseHex()
	
	local docValue = {
		ratings = {
			[ userId ] = {
				rating = 5,
			},
		},
	}
	
	rxTest:expectEqual( LrmAssetUtils.getDefaultAssetRating( docValue ), 5 )
	
	docValue = {
		ratings = {
			[ 'asdfwef' ] = {
				rating = 2,
			}
		}
	}
	
	rxTest:expectEqual( LrmAssetUtils.getDefaultAssetRating( docValue ), 0 )
	
	docValue.ratings = 'foo'
	
	rxTest:expectEqual( LrmAssetUtils.getDefaultAssetRating( docValue ), 0 )
	
	docValue = {
		ratings = {
			[ userId ] = {
				_atomic = 'merge',
				date = '2015-11-09',
			},
		},
	}
	
	rxTest:expectEqual( LrmAssetUtils.getDefaultAssetRating( docValue ), 0 )
	
end

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

function LrmAssetUtilsTest.rxTestGetDefaultAssetReview( rxTest )

	local userId = KSIdGenerator.uuidInLowercaseHex()
	
	local docValue = {
		reviews = {
			[ userId ] = {
				flag = 'pick',
			},
		},
	}
	
	rxTest:expectEqual( LrmAssetUtils.getDefaultAssetReview( docValue ), 'pick' )
	
	docValue = {
		ratings = {
			[ 'asdfwef' ] = {
				flag = 2,
			}
		}
	}
	
	rxTest:expectEqual( LrmAssetUtils.getDefaultAssetReview( docValue ), 'unflagged' )
	
	docValue.ratings = 'foo'
	
	rxTest:expectEqual( LrmAssetUtils.getDefaultAssetReview( docValue ), 'unflagged' )
	
	docValue = {
		reviews = {
			[ userId ] = {
				_atomic = 'merge',
				date = '2015-11-09',
			},
		},
	}
	
	rxTest:expectEqual( LrmAssetUtils.getDefaultAssetReview( docValue ), 'unflagged' )
	
end

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

function LrmAssetUtilsTest.rxTestIsAdobeCaptured( rxTest )

	local docValue = {
		xmp = {
			xmp = {
				CreatorTool = "Adobe Camera 1.1" 		-- LriOS version < 4.4.0
			}
		}
	}
	rxTest:expectEqual( LrmAssetUtils.getCapturedWithAdobeCamera( docValue ), true )

	docValue.xmp.xmp.CreatorTool = nil
	rxTest:expectEqual( LrmAssetUtils.getCapturedWithAdobeCamera( docValue ), false )

	docValue.xmp.xmp.CreatorTool = 'Thio' 				-- historical LriOS
	rxTest:expectEqual( LrmAssetUtils.getCapturedWithAdobeCamera( docValue ), true )

	docValue.xmp.xmp.CreatorTool = 'Lightroom CC (iOS)' -- HDR and Long Exposure
	rxTest:expectEqual( LrmAssetUtils.getCapturedWithAdobeCamera( docValue ), true )

	-- must fail if xmp.aux.IsLrCameraCapture is not set
	docValue.xmp.xmp.CreatorTool = 'Adobe Lightroom' 	-- LrA, LriOS version >= 5.0.0
	rxTest:expectEqual( LrmAssetUtils.getCapturedWithAdobeCamera( docValue ), false )

	docValue.xmp.xmp.CreatorTool = 'Lightroom' 			-- LrA version 4.3.0, 4.4.0, LriOS 4.4
	rxTest:expectEqual( LrmAssetUtils.getCapturedWithAdobeCamera( docValue ), true )


	docValue.xmp.xmp.CreatorTool = 'Adobe Lightroom' 	-- LrA, LriOS version >= 5.0.0
	docValue.xmp.aux = {
		IsLrCameraCapture = true,
	}
	rxTest:expectEqual( LrmAssetUtils.getCapturedWithAdobeCamera( docValue ), true )
end

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

local function makeXmpDocValue()

	return {
		xmp = {
			dc = {
				rights = 'Copyright',
			},
			exif = {
				ExposureTime = { 100, 1 },
				FNumber = { 100, 1 },
				ApertureValue = { 100, 1 },
				FocalLength = { 100, 1 },
				ISOSpeedRatings = 100,
			},
			tiff = {
				Make = 'Make',
				Model = 'Model',
			},
			aux = {
				Lens = 'Lens',
			}
		}
	}
	
end

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

local function alterExif( docValue, key, value )

	docValue.xmp.exif[ key ] = value
	
	return docValue
	
end

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

function LrmAssetUtilsTest.rxTestGetXmp( rxTest )

	local xmp = LrmAssetUtils.getXmp
	
	local doc = makeXmpDocValue()
	
	rxTest:expectEqual( xmp( doc ).copyright, 'Copyright' )
	rxTest:expectEqual( xmp( doc ).make, 'Make' )
	rxTest:expectEqual( xmp( doc ).model, 'Model' )
	rxTest:expectEqual( xmp( doc ).cameraMake, 'Make' )
	rxTest:expectEqual( xmp( doc ).cameraModel, 'Model' )
	rxTest:expectEqual( xmp( doc ).lens, 'Lens' )
	
	-- ExposureTime
	
	rxTest:expectEqual( xmp( doc ).exposureTime, '100' )
	
	alterExif( doc, 'ExposureTime', { 100 } )
	rxTest:expectEqual( xmp( doc ).exposureTime, '100' )
	
	alterExif( doc, 'ExposureTime', { 100, 2 } )
	rxTest:expectEqual( xmp( doc ).exposureTime, '50.0' )
	
	alterExif( doc, 'ExposureTime', { 1, 2 } )
	rxTest:expectEqual( xmp( doc ).exposureTime, '1/2' )
	
	alterExif( doc, 'ExposureTime', nil )
	rxTest:expectEqual( xmp( doc ).exposureTime, '' )
	
	alterExif( doc, 'ExposureTime', { 2, 0 } )
	rxTest:expectEqual( xmp( doc ).exposureTime, '2' )
	
	-- FNumber
	
	rxTest:expectEqual( xmp( doc ).fnumber, '100.0' )
	
	alterExif( doc, 'FNumber', { 100 } )
	rxTest:expectEqual( xmp( doc ).fnumber, '100.0' )
	
	alterExif( doc, 'FNumber', { 100, 1 } )
	rxTest:expectEqual( xmp( doc ).fnumber, '100.0' )
	
	alterExif( doc, 'FNumber', { 100, 50 } )
	rxTest:expectEqual( xmp( doc ).fnumber, '2.0' )
	
	alterExif( doc, 'FNumber', nil )
	rxTest:expectEqual( xmp( doc ).fnumber, '' )
	
	alterExif( doc, 'FNumber', { 2, 0 } )
	rxTest:expectEqual( xmp( doc ).fnumber, '2.0' )
	
	-- Aperture
	
	rxTest:expectEqual( xmp( doc ).apertureValue, '100.0' )
	
	alterExif( doc, 'ApertureValue', { 100 } )
	rxTest:expectEqual( xmp( doc ).apertureValue, '100.0' )
	
	alterExif( doc, 'ApertureValue', { 100, 1 } )
	rxTest:expectEqual( xmp( doc ).apertureValue, '100.0' )
	
	alterExif( doc, 'ApertureValue', { 100, 50 } )
	rxTest:expectEqual( xmp( doc ).apertureValue, '2.0' )
	
	alterExif( doc, 'ApertureValue', nil )
	rxTest:expectEqual( xmp( doc ).apertureValue, '' )
	
	alterExif( doc, 'ApertureValue', { 2, 0 } )
	rxTest:expectEqual( xmp( doc ).apertureValue, '2.0' )
	
	-- FocalLength
	
	rxTest:expectEqual( xmp( doc ).focalLength, '100' )
	
	alterExif( doc, 'FocalLength', { 100 } )
	rxTest:expectEqual( xmp( doc ).focalLength, '100' )
	
	alterExif( doc, 'FocalLength', { 100, 1 } )
	rxTest:expectEqual( xmp( doc ).focalLength, '100' )
	
	alterExif( doc, 'FocalLength', { 100, 50 } )
	rxTest:expectEqual( xmp( doc ).focalLength, '2' )
	
	alterExif( doc, 'FocalLength', nil )
	rxTest:expectEqual( xmp( doc ).focalLength, '' )
	
	alterExif( doc, 'FocalLength', { 2, 0 } )
	rxTest:expectEqual( xmp( doc ).focalLength, '2' )
	
	-- ISO Speed rating
	
	rxTest:expectEqual( xmp( doc ).isoSpeedRatings, '100' )
	
	alterExif( doc, 'ISOSpeedRatings', 20 )
	rxTest:expectEqual( xmp( doc ).isoSpeedRatings, '20' )
	
	alterExif( doc, 'ISOSpeedRatings', nil )
	rxTest:expectEqual( xmp( doc ).isoSpeedRatings, '' )
	
	alterExif( doc, 'ISOSpeedRatings', 205 )
	rxTest:expectEqual( xmp( doc ).isoSpeedRatings, '205' )
	
end

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

function LrmAssetUtilsTest.rxTestPreferableBinaryForDevelop( rxTest )

	local LrmConfig = require 'LrmConfig'
	
	local preferedBinary = assert( LrmAssetUtils.preferableBinaryForDevelop )
	
	rxTest:expectError( preferedBinary, nil )
	
	local docValue = makeOriginalDocValue()
	
	rxTest:expectEqual( LrmConfig.StrategyPreferMaster, preferedBinary( docValue, LrmConfig.StrategyPreferMaster ) )
	
	rxTest:expectEqual( LrmConfig.StrategyPreferMaster, preferedBinary( docValue, LrmConfig.StrategyPreferProxy ) )
	
	docValue = makeOriginalAndProxyDocValue()
	
	rxTest:expectEqual( LrmConfig.StrategyPreferMaster, preferedBinary( docValue, LrmConfig.StrategyPreferMaster ) )
	
	rxTest:expectEqual( LrmConfig.StrategyPreferProxy, preferedBinary( docValue, LrmConfig.StrategyPreferProxy ) )
	
	docValue = {
		_localOnly = {
			localUrl = '/localUrl'
		}
	}
	
	rxTest:expectEqual( LrmConfig.StrategyPreferMaster, preferedBinary( docValue, LrmConfig.StrategyPreferMaster ) )
	
	rxTest:expectEqual( LrmConfig.StrategyPreferMaster, preferedBinary( docValue, LrmConfig.StrategyPreferProxy ) )
	
	docValue = makeProxyDocValue()

	rxTest:expectEqual( LrmConfig.StrategyPreferProxy, preferedBinary( docValue, LrmConfig.StrategyPreferMaster ) )
	
	rxTest:expectEqual( LrmConfig.StrategyPreferProxy, preferedBinary( docValue, LrmConfig.StrategyPreferProxy ) )
	
end

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

function LrmAssetUtilsTest.rxTesthasDownloadableExternalXmpDevelop( rxTest )

	local docValue = {
		_serverProvidedMetadata = {
			base = "https://photos.adobe.io/v2/catalogs/a4be0605937b4bc5aa3092e51fd90dc4/",
			created = "2017-08-17T11:57:14.343553Z",
			links = {
				["/rels/xmp/develop"] = {
					href = "/v2/catalogs/a4be0605937b4bc",
					invalid = true,
				},
			},
		},
		develop = {
			xmpCameraRaw = {
				sha256 = "deadbeaf",
			}
		}
	}

	rxTest:expectEqual( true, LrmAssetUtils.hasDownloadableExternalXmpDevelop( docValue ) )

	docValue.invalid = nil
	rxTest:expectEqual( true, LrmAssetUtils.hasDownloadableExternalXmpDevelop( docValue ) )

	KSTableUtils.setNested( docValue, nil, '_serverProvidedMetadata', 'links', '/rels/xmp/develop' )
	rxTest:expectEqual( false, LrmAssetUtils.hasDownloadableExternalXmpDevelop( docValue ) )

	-- Test an inconsistent docValue
	docValue.develop = nil
	rxTest:expectEqual( false, LrmAssetUtils.hasDownloadableExternalXmpDevelop( docValue ) )

end

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

return WFRxTestCase.wrapSuite( 'LrmAssetUtilsTest', LrmAssetUtilsTest )
