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

WFCatExportMetadataTest.lua

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

ADOBE CONFIDENTIAL
------------------
Copyright 2016 Adobe Systems Incorporated
All Rights Reserved.

NOTICE: All information contained herein is, and remains 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 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 Systems Incorporated.

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

local WFPlatformInfo = require "WFPlatformInfo"

-- Disabled on iOS and Android because WFXmp is not present there

if WFPlatformInfo.isAndroid or WFPlatformInfo.isiOS then
       return {}
end

	-- WF.oz_client.managedCatalog.metadata
local WFCatExportMetadata = require 'WFCatExportMetadata'
local WFXMLNS = require 'WFXMLNS'
local WFXmp = require 'WFXmp'

--------------------------------------------------------------------------------
local WFCatExportMetadataTest = {}

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

local function setXmpInfoAndValidateSimpleValue( 
		xmpDoc, namespace, fieldName, expectedValue )
	
	local metadata = WFCatExportMetadata.setXmpInfo( xmpDoc )
	local actualValue = metadata:get( namespace, fieldName )
	
	local assertString = string.format( "%s.%s expected: '%s', actual: '%s'",
		namespace, fieldName, expectedValue, actualValue )
	
	assert( actualValue == expectedValue, assertString )
end

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

function WFCatExportMetadataTest.testAuxMetadataSetting()
	
	local xmpDoc = {
		aux = {
			Lens = "My Lens",
			SerialNumber = "323nbnb3413jjj",
		}
	}
	setXmpInfoAndValidateSimpleValue( 
		xmpDoc, WFXMLNS.aux, 'Lens', 'My Lens' )
	
end

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

function WFCatExportMetadataTest.testIntegerField()

	local xmpDoc = {
		exif = {
			FocalLengthIn35mmFilm = 101,
		}
	}
	
	setXmpInfoAndValidateSimpleValue( 
		xmpDoc, WFXMLNS.exif, 'FocalLengthIn35mmFilm', '101' )

end

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

function WFCatExportMetadataTest.testFractionField()
	-- Test for normal value
	local xmpDoc = {
		exif = {
			ApertureValue = { 4, 1 }
		}
	}
	setXmpInfoAndValidateSimpleValue( 
		xmpDoc, WFXMLNS.exif, 'ApertureValue', '4/1' )
	
	
	-- Test for special values
	xmpDoc.exif.SubjectDistance = 'infinite'
	setXmpInfoAndValidateSimpleValue( 
		xmpDoc, WFXMLNS.exif, 'SubjectDistance', '4294967295' )

	xmpDoc.exif.SubjectDistance = 'unknown'
	setXmpInfoAndValidateSimpleValue( 
		xmpDoc, WFXMLNS.exif, 'SubjectDistance', '0' )
	
	--ashj: TODO Test for negative??

end

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

function WFCatExportMetadataTest.testDateField()
	
	-- Here are some sample XMP dates from the "all raw" data set
	-- (numers were regex'd for uniformity)
	--	"2345-12-28T01:23:45"
	--	"2345-12-28T01:23:45+06:00"
	--	"2345-12-28T01:23:45-06:00"
	--	"2345-12-28T01:23:45.67"
	--	"2345-12-28T01:23:45Z"
	local xmpDoc = {
		exif = {
			DateTimeOriginal = '2345-12-28T01:23:45+06:00'
		}
	}
	setXmpInfoAndValidateSimpleValue( 
		xmpDoc, WFXMLNS.exif, 'DateTimeOriginal', '2345-12-28T01:23:45+06:00' )

end
--------------------------------------------------------------------------------

function WFCatExportMetadataTest.testBooleanField()
	
	-- Test NO data
	setXmpInfoAndValidateSimpleValue( 
		{}, WFXMLNS.xapRights, 'Marked', nil )
	
	-- Test True
	local xmpDoc = {
		xmpRights = {
			Marked = true,
		}
	}
	
	setXmpInfoAndValidateSimpleValue( 
		xmpDoc, WFXMLNS.xapRights, 'Marked', 'True' )
		
	
	-- Test False
	xmpDoc.xmpRights.Marked = false
	setXmpInfoAndValidateSimpleValue( 
		xmpDoc, WFXMLNS.xapRights, 'Marked', 'False' )

end

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

function WFCatExportMetadataTest.testEnumField()
	local xmpDoc = {
		exif = {
			ExposureProgram = "manual",
		}
	}
	
	setXmpInfoAndValidateSimpleValue( 
		xmpDoc, WFXMLNS.exif, 'ExposureProgram', '1' )

end

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

function WFCatExportMetadataTest.testConcatenatedStringList()
	local xmpDoc = {
		dc = {
			creator = {"user1", "user2"},
		}
	}
	
	local metadata = WFCatExportMetadata.setXmpInfo( xmpDoc )
	
	local creatorList = metadata:getStringList( WFXMLNS.dc, 'creator' )
	assert( type( creatorList ) == 'table', "exif.creator has to be table")
	assert( creatorList[ 1 ] == 'user1', "exif.creator should be 'user1'")
	assert( creatorList[ 2 ] == 'user2', "exif.creator should be 'user2'")

end

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

function WFCatExportMetadataTest.testFirstArrayElementAsInteger()
	local xmpDoc = {
		exif = {
			ISOSpeedRatings = 50,
		}
	}
	
	local metadata = WFCatExportMetadata.setXmpInfo( xmpDoc )
	local speedRatingList = metadata:getStringList( WFXMLNS.exif, 'ISOSpeedRatings' )
	
	assert( type( speedRatingList ) == 'table', "exif.ISOSpeedRatings should be a table" )
	assert( #speedRatingList == 1, "exif.ISOSpeedRatings should be of size 1" )
	assert( speedRatingList[ 1 ] == '50' , "exif.ISOSpeedRatings[1] should be '50'" )

end

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

function WFCatExportMetadataTest.testFieldType()
	
	local xmpDoc = {
		exif = {
			FlashFired = true,
		}
	}
	local metadata = WFCatExportMetadata.setXmpInfo( xmpDoc )
	local fieldPath = metadata:composeStructFieldPath( WFXMLNS.exif, 'Flash', WFXMLNS.exif, 'Fired' )
	local actualValue = metadata:get( WFXMLNS.exif, fieldPath )
	
	assert( actualValue == "True", "exif.Flash.Fired expected: 'True', actual: '"..tostring( actualValue ).."'" )
	
end

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

function WFCatExportMetadataTest.testKeywords()
	local xmpDoc = {
			dc = {
				subject = {
					North_America = true,
					Eastern_Canada = true, 
					ecology = true,
				}
			}
		}
	
	local metadata = WFCatExportMetadata.setXmpInfo( xmpDoc )
	
	local keywordList = metadata:getStringList( WFXMLNS.dc, 'subject' )
	
	assert( type( keywordList ) == 'table', "dc.Subject should be a table" )
	assert( #keywordList == 3, "dc.Subject should be of size 1" )
	
	for i, keyword in ipairs( xmpDoc.dc.subject ) do
		
		local foundKeyword = false
		
		for j, exportKeyword in ipairs( keywordList ) do
			foundKeyword = keyword == exportKeyword
			
			if foundKeyword then
				break
			end
		end
		
		assert( foundKeyword, "failed to export keyword: " .. keyword )
	end

end

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

function WFCatExportMetadataTest.testRating()

	local docValue = {
		ratings = {
			fe5e6354ab0d22a3bcdd9247a8438967d = {
				rating = 3,
				date = "2013-08-10T08:32:13Z",
			},
		}
	}

	local metadata = WFCatExportMetadata.setExtraXmpInfo( "fe5e6354ab0d22a3bcdd9247a8438967d", docValue )
	local rating = metadata:get( WFXMLNS.xap, 'Rating' )
	
	assert( rating == "3", "xap.Rating should be of 3" )


	--Test multiple rating values
	
	docValue = {
		ratings = {
			be9e114ab0d95a3bc9ed267a8438935c = {
				rating = 4,
				date = "2013-07-10T08:32:13Z",
			},
			fe5e6354ab0d22a3bcdd9247a8438967d = {
				rating = 3,
				date = "2013-08-10T08:32:13Z",
			},
		}
	}
	
	metadata = WFCatExportMetadata.setExtraXmpInfo( "fe5e6354ab0d22a3bcdd9247a8438967d", docValue )
	rating = metadata:get( WFXMLNS.xap, 'Rating' )
	
	assert( rating == "3", "xap.Rating should be of 3" )

end

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

function WFCatExportMetadataTest.testFlag()

	local docValue = {
		reviews = {
			fe5e6354ab0d22a3bcdd9247a8438967d = {
				flag = "pick",
				date = "2013-08-10T08:32:13Z",
			},
		}
	}

	local metadata = WFCatExportMetadata.setExtraXmpInfo( "fe5e6354ab0d22a3bcdd9247a8438967d", docValue )
	local review = metadata:get( WFXMLNS.dm, 'good' )
	
	assert( review == "True", "dm.good should be True" )


	--Test multiple rating values

	docValue = {
		reviews = {
			be9e114ab0d95a3bc9ed267a8438935c = {
				flag = "reject",
				date = "2013-07-10T08:32:13Z",
			},
			fe5e6354ab0d22a3bcdd9247a8438967d = {
				flag = "pick",
				date = "2013-08-10T08:32:13Z",
			},
		}
	}

	metadata = WFCatExportMetadata.setExtraXmpInfo( "be9e114ab0d95a3bc9ed267a8438935c", docValue )
	review = metadata:get( WFXMLNS.dm, 'good' )

	assert( review == "False", "dm.good should be of False" )

end

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

function WFCatExportMetadataTest.testLocation()
	local docValue = {
		location = {
			latitude = 33.502825,
			longitude = -117.662358,
			altitude = 34.8,
		}
	}
	
	local metadata = WFCatExportMetadata.setExtraXmpInfo( nil, docValue )
	assert( metadata:get( WFXMLNS.exif, 'GPSVersionID' ) == "2.2.0.0",
		"exif.GPSVersionID should be '2.2.0.0'")
	assert( metadata:get( WFXMLNS.exif, 'GPSLatitude' ) == "33,30.1695N",
		"exif.GPSLatitude should be '33,30.1695N'")
	assert( metadata:get( WFXMLNS.exif, 'GPSLongitude' ) == "117,39.74148W",
		"exif.GPSLongitude should be '117,39.74148W'")
	assert( metadata:get( WFXMLNS.exif, 'GPSAltitude' ) == "174/5",
		"exif.GPSLongitude should be '174/5'")

end

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

function WFCatExportMetadataTest.testCompleteXmp()
	local docValue = {
		xmp = {
			dc = {
				creator = {"user1", "user2"},
			}
		},

		ratings = {
			fe5e6354ab0d22a3bcdd9247a8438967d = {
				rating = 3,
				date = "2013-08-10T08:32:13Z",
			},
		}
	}


	local metadata = WFCatExportMetadata.createCompleteXmp( docValue, "fe5e6354ab0d22a3bcdd9247a8438967d" )

	local creatorList = metadata:getStringList( WFXMLNS.dc, 'creator' )
	assert( type( creatorList ) == 'table', "exif.creator has to be table")
	assert( creatorList[ 1 ] == 'user1', "exif.creator should be 'user1'")
	assert( creatorList[ 2 ] == 'user2', "exif.creator should be 'user2'")

	local rating = metadata:get( WFXMLNS.xap, 'Rating' )
	assert( rating == "3", "xap.Rating should be of 3" )

end

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

function WFCatExportMetadataTest.testCompleteXmpWithDelete()
	local docValue = {
		xmp = {
			dc = {
				creator = {"user1", "user2"},
			}
		},

		ratings = {
			fe5e6354ab0d22a3bcdd9247a8438967d = {
				rating = 3,
				date = "2013-08-10T08:32:13Z",
			},
		}
	}

	local xmp = WFXmp.WFXmp()
	xmp:set( WFXMLNS.xap, 'Rating', "2" )
	xmp:set( WFXMLNS.dm, 'good', true )

	-- Test for delete = false
	local metadata = WFCatExportMetadata.createCompleteXmp( docValue, "fe5e6354ab0d22a3bcdd9247a8438967d", 
		tostring( xmp:serialize() ), false )

	local creatorList = metadata:getStringList( WFXMLNS.dc, 'creator' )
	assert( type( creatorList ) == 'table', "exif.creator has to be table")
	assert( creatorList[ 1 ] == 'user1', "exif.creator should be 'user1'")
	assert( creatorList[ 2 ] == 'user2', "exif.creator should be 'user2'")

	local rating = metadata:get( WFXMLNS.xap, 'Rating' )
	assert( rating == "3", "xap.Rating should be of 3" )
	
	local good = metadata:get( WFXMLNS.dm, 'good' )
	assert( good == "True", "dm.good should be of True" )
	
	
	-- Test for delete = true
	metadata = WFCatExportMetadata.createCompleteXmp( docValue, "fe5e6354ab0d22a3bcdd9247a8438967d", 
		tostring( xmp:serialize() ), true )

	creatorList = metadata:getStringList( WFXMLNS.dc, 'creator' )
	assert( type( creatorList ) == 'table', "exif.creator has to be table")
	assert( creatorList[ 1 ] == 'user1', "exif.creator should be 'user1'")
	assert( creatorList[ 2 ] == 'user2', "exif.creator should be 'user2'")

	rating = metadata:get( WFXMLNS.xap, 'Rating' )
	assert( rating == "3", "xap.Rating should be of 3" )
	
	good = metadata:get( WFXMLNS.dm, 'good' )
	assert( good == nil, "dm.good should be of nil" )

end
--------------------------------------------------------------------------------

function WFCatExportMetadataTest.testOrientation()
	local docValue = {
		develop = {
			userOrientation = 5,
		},
		xmp = {
			tiff = {
				Orientation = "left bottom", -- corresponds to 8
			},
		},
	}

	local metadata = WFCatExportMetadata.createCompleteXmp( docValue, "fe5e6354ab0d22a3bcdd9247a8438967d" )

	local orientation = metadata:get( WFXMLNS.tiff, 'Orientation' )
	assert( orientation == "5", "tiff.Orientation should be 5")

end

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

function WFCatExportMetadataTest.testEditHistory()
	local docValue = {
		develop = {
			userUpdated = '2017-03-22T05:34:48.583Z',
		},
	}
	local userId = "fe5e6354ab0d22a3bcdd9247a8438967d"

	local metadata = WFCatExportMetadata.createCompleteXmp( docValue, userId )

	local event = metadata:get( WFXMLNS.xmpMM, "History[1]/stEvt:action")
	assert( event == "edited", "Incorrect History[1]/stEvt:action")
	local when = metadata:get( WFXMLNS.xmpMM, "History[1]/stEvt:when")
	assert( when == "2017-03-22T05:34:48.583Z", "Incorrect history date value")
	
	
	-- Test the case where there is an already existing event
	docValue = {
		develop = {
			userUpdated = '2017-07-05T00:01:22.342Z',
		},
	}
	metadata = WFCatExportMetadata.createCompleteXmp( docValue, userId, tostring( metadata:serialize()) )
	event = metadata:get( WFXMLNS.xmpMM, "History[1]/stEvt:action")
	assert( event == "edited", "Incorrect History[1]/stEvt:action")
	when = metadata:get( WFXMLNS.xmpMM, "History[1]/stEvt:when")
	assert( when == "2017-03-22T05:34:48.583Z", "Incorrect history date value")
	
	event = metadata:get( WFXMLNS.xmpMM, "History[2]/stEvt:action")
	assert( event == "edited", "Incorrect History[2]/stEvt:action")
	when = metadata:get( WFXMLNS.xmpMM, "History[2]/stEvt:when")
	assert( when == "2017-07-05T00:01:22.342Z", "Incorrect history date value")

end

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

function WFCatExportMetadataTest.testFaceRemoval()
	local docValue = {
		develop = {
			userUpdated = '2017-03-22T05:34:48.583Z',
		},
	}
	local userId = "fe5e6354ab0d22a3bcdd9247a8438967d"
	
	
	-- Test the case where only one face info is present
	
	local WFXmp = assert( require 'WFXmp', 'namespace exists' )
	local xmp = assert( WFXmp.WFXmp(), 'can create xmp' )
	
	WFXmp.registerNamespace( WFXMLNS.mwgRegions, "mwg-rs" )
	
	local regionListPath = xmp:composeStructFieldPath( WFXMLNS.mwgRegions, 'Regions', WFXMLNS.mwgRegions, 'RegionList' )
	local pathToAddedRegion = xmp:appendStructItemToArray( WFXMLNS.mwgRegions, regionListPath, true )
	xmp:setStruct( WFXMLNS.mwgRegions, pathToAddedRegion, WFXMLNS.mwgRegions, "Type", "Face" )
	xmp:setStruct( WFXMLNS.mwgRegions, pathToAddedRegion, WFXMLNS.mwgRegions, "Name", "John" )

	xmp = WFCatExportMetadata.createCompleteXmp( docValue, userId, tostring( xmp:serialize() ), false, true )

	assert( xmp:hasProperty( WFXMLNS.mwgRegions, 'Regions' ) == false, 'Region should get removed' )
	
	
	-- Test the case where multiple faces are present
	
	xmp = assert( WFXmp.WFXmp(), 'can create xmp' )
	
	regionListPath = xmp:composeStructFieldPath( WFXMLNS.mwgRegions, 'Regions', WFXMLNS.mwgRegions, 'RegionList' )
	pathToAddedRegion = xmp:appendStructItemToArray( WFXMLNS.mwgRegions, regionListPath, true )
	xmp:setStruct( WFXMLNS.mwgRegions, pathToAddedRegion, WFXMLNS.mwgRegions, "Type", "Face" )
	xmp:setStruct( WFXMLNS.mwgRegions, pathToAddedRegion, WFXMLNS.mwgRegions, "Name", "John" )
	
	pathToAddedRegion = xmp:appendStructItemToArray( WFXMLNS.mwgRegions, regionListPath, true )
	xmp:setStruct( WFXMLNS.mwgRegions, pathToAddedRegion, WFXMLNS.mwgRegions, "Type", "Face" )
	xmp:setStruct( WFXMLNS.mwgRegions, pathToAddedRegion, WFXMLNS.mwgRegions, "Name", "Tina" )

	xmp = WFCatExportMetadata.createCompleteXmp( docValue, userId, tostring( xmp:serialize() ), false, true )

	assert( xmp:hasProperty( WFXMLNS.mwgRegions, 'Regions' ) == false, 'Region should get removed' )
	
	
	-- Test the case where multiple type of regions are present
	
	xmp = assert( WFXmp.WFXmp(), 'can create xmp' )
	
	regionListPath = xmp:composeStructFieldPath( WFXMLNS.mwgRegions, 'Regions', WFXMLNS.mwgRegions, 'RegionList' )
	pathToAddedRegion = xmp:appendStructItemToArray( WFXMLNS.mwgRegions, regionListPath, true )
	xmp:setStruct( WFXMLNS.mwgRegions, pathToAddedRegion, WFXMLNS.mwgRegions, "Type", "Face" )
	xmp:setStruct( WFXMLNS.mwgRegions, pathToAddedRegion, WFXMLNS.mwgRegions, "Name", "John" )
	
	pathToAddedRegion = xmp:appendStructItemToArray( WFXMLNS.mwgRegions, regionListPath, true )
	xmp:setStruct( WFXMLNS.mwgRegions, pathToAddedRegion, WFXMLNS.mwgRegions, "Type", "Focus" )

	xmp = WFCatExportMetadata.createCompleteXmp( docValue, userId, tostring( xmp:serialize() ), false, true )

	assert( xmp:hasProperty( WFXMLNS.mwgRegions, 'Regions' ) == true, 'Regions otherthan faces should be retained' )
	assert( xmp:countArrayItems( WFXMLNS.mwgRegions, regionListPath ) == 1, 
		'Regions otherthan faces should be retained, hence count should be 1' )
	local itemPathAtFirstIndex = xmp:composeArrayItemPath( WFXMLNS.mwgRegions, regionListPath, 1 )
	local regionType = xmp:getStruct( WFXMLNS.mwgRegions, itemPathAtFirstIndex, WFXMLNS.mwgRegions, "Type" )
	assert( regionType == "Focus", "All regions otherthan faces should be retained" )

end

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

function WFCatExportMetadataTest.testPersonInImageRemoval()
	local docValue = {
		develop = {
			userUpdated = '2017-03-22T05:34:48.583Z',
		},
	}
	local userId = "fe5e6354ab0d22a3bcdd9247a8438967d"
	
	
	-- Test the case where only one face info is present
	
	local WFXmp = assert( require 'WFXmp', 'namespace exists' )
	local xmp = assert( WFXmp.WFXmp(), 'can create xmp' )
	
	
	-- No personInImage section
	local xmpResult = WFCatExportMetadata.createCompleteXmp( docValue, userId, tostring( xmp:serialize() ), false, true )
	assert( not xmpResult:hasProperty( WFXMLNS.Iptc4xmpExt, 'PersonInImage' ), "PersonInImage should be removed" )
	
	-- Has PersonInImage with removeFaceInfo true
	xmp:setStringList( WFXMLNS.Iptc4xmpExt, 'PersonInImage', { "Jack" }, true )
	xmpResult = WFCatExportMetadata.createCompleteXmp( docValue, userId, tostring( xmp:serialize() ), false, true )
	assert( not xmpResult:hasProperty( WFXMLNS.Iptc4xmpExt, 'PersonInImage' ), "PersonInImage should be removed" )
	
	-- Has PersonInImage with removeFaceInfo false
	xmpResult = WFCatExportMetadata.createCompleteXmp( docValue, userId, tostring( xmp:serialize() ), false, false )
	assert( xmpResult:hasProperty( WFXMLNS.Iptc4xmpExt, 'PersonInImage' ), "PersonInImage should be retained" )
end
--==============================================================================

return WFCatExportMetadataTest
