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

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

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

local KSDate = require 'KSDate'

local WFRxTestCase = require 'WFRxTestCase'
local WFCatAssetTestUtils = require 'WFCatAssetTestUtils'
local KSIdGenerator = require 'KSIdGenerator'
local WFPlatformInfo = require 'WFPlatformInfo'
local WFCatMockCatalog = require 'WFCatMockCatalog'
local LrmLibraryAssetEditInfoImp = require 'LrmLibraryAssetEditInfoImp'
local WFDeviceInfo = require 'WFDeviceInfo'

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

local LrmLibraryAssetEditInfoImpTest = {}

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

local catalogOptions = {
	indexDefinitions = 'LrmCatalogIndexDefinitions.lua'
}

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

function LrmLibraryAssetEditInfoImpTest.rxTestGetAssetLatestEditDetails( rxTest )

	rxTest:setTimeLimit(5)

	local wfCatalog = WFCatMockCatalog.createFakeWFCatalog( rxTest, nil, nil, catalogOptions )

	-- testing the happy path

	local editUserId = KSIdGenerator.uuidInLowercaseHex()
	local assetID = KSIdGenerator.uuidInLowercaseHex()

	rxTest:expectSingleValue(
		wfCatalog:docStore():bulkSetDocValue {
			{
				_id = assetID,
				type = "asset",
				subtype = "image",
				captureDate = "2016",
				develop = {
					userUpdated = "A long time ago",
					device = "Some new Device",
				},
				_serverProvidedMetadata = {
					developedByUser = {
						id = editUserId,
					},
				}
			},
		},

	':ignore:' )

	rxTest:expectSingleValue(
			wfCatalog:docStore():bulkSetDocValue {
				{
					_id = editUserId,
					_serverProvidedMetadata = {
						full_name = "Asterix of Gaul",
						first_name = "Asterix",
						last_name = "of Gaul",
					},
					type = "feedbackuser",
				}
			}, ':ignore:')


	local result = LrmLibraryAssetEditInfoImp.getAssetLatestEditDetails( { _wfCatalog = wfCatalog }, assetID )

	rxTest:expectSingleValue( result.value, {
				userUpdated = "A long time ago",
				userDevice = "Some new Device",
				userName = "Asterix of Gaul",
			} )

	-- testing the case where there is no developedByUser

	assetID = KSIdGenerator.uuidInLowercaseHex()

	rxTest:expectSingleValue(
		wfCatalog:docStore():bulkSetDocValue {
			{
				_id = assetID,
				type = "asset",
				subtype = "image",
				captureDate = "2016",
				develop = {
					userUpdated = "A long time ago",
					device = "Some new Device",
				},
			},
		},

	':ignore:' )

	result = LrmLibraryAssetEditInfoImp.getAssetLatestEditDetails( { _wfCatalog = wfCatalog }, assetID )

	rxTest:expectSingleValue( result.value, {
				userUpdated = "A long time ago",
				userDevice = "Some new Device",
			} )

end

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

local function addTestAsset( rxTest, catalog, localId, params )

	local docId = KSIdGenerator.uuidInLowercaseHex()

	local opts = { }

	if params.spaceId then
		opts.isSpaceAsset = true
		opts.spaceId = params.spaceId
	end

	local assetDoc = WFCatAssetTestUtils.createAssetDocument( rxTest, catalog, docId, opts )
	assetDoc._localId = localId

	assetDoc._serverProvidedMetadata.importedByUser = {
		id = params.importedByUser,
	}
	assetDoc._serverProvidedMetadata.developedByUser = params.maybeDevelopedByUser
	assetDoc.captureDate = params.maybeCaptureDate
	assetDoc.develop = params.maybeDevelop
	assetDoc.importSource.fileName = params.maybeFileName
	assetDoc.xmp = {
		exif = {
			DateTimeOriginal = params.maybeDateTimeOriginal,
		},
		photoshop = {
			DateCreated = params.maybeDateCreated,
		},
		xmp = {
			CreateDate = params.maybeCreateDate,
		}
	}

	rxTest:waitFor( catalog:docStore():bulkSetDocValue { assetDoc } )

	return docId

end

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

function LrmLibraryAssetEditInfoImpTest.rxTestGetOtherClientEditDetails( rxTest )

	rxTest:setTimeLimit( 5 )

	local fakeWFCatalog = WFCatMockCatalog.createFakeWFCatalog( rxTest, nil, nil, catalogOptions )

	-- Create a fake user with an associated feedbackuser document

	local editUserId = KSIdGenerator.uuidInLowercaseHex()

	rxTest:expectSingleValue(
			fakeWFCatalog:docStore():bulkSetDocValue {
				{
					_id = editUserId,
					_serverProvidedMetadata = {
						full_name = "Asterix of Gaul",
						first_name = "Asterix",
						last_name = "of Gaul",
					},
					type = "feedbackuser",
				}
			}, ':ignore:')

	local localDocId1 = 2
	local docId1 = addTestAsset( rxTest, fakeWFCatalog, localDocId1, {
		maybeFileName = 'File1.JPG',
		maybeDevelop = {
			userUpdated = "A long time ago",
			device = "A device that isn't thisDevice",
		},
		maybeDevelopedByUser = {
			id = editUserId,
		},
	} )

	local localDocId2 = 3
	local docId2 = addTestAsset( rxTest, fakeWFCatalog, localDocId2, {
		maybeFileName = 'File2.JPG',
		maybeDevelop = {
			userUpdated = "2023-06-08T20:41:31.478821Z",
			device = WFDeviceInfo.deviceDescription()
		},
		maybeDevelopedByUser = nil
	} )

	-- the returned table should have data from both the asset and feedback document

	local doc1OtherClientEditDetailsStream = rxTest:observe( 
		LrmLibraryAssetEditInfoImp.getOtherClientEditDetails( { _wfCatalog = fakeWFCatalog }, docId1 ).value 
		-- For ease of testing - lets not do the "time" thing
		:map( function( details )
			details.userUpdatedAsString = details.userUpdatedAsString and type( details.userUpdatedAsString )
			return details
		end )

	)

	doc1OtherClientEditDetailsStream:expectDataWithinTime( 1,
		{
			hasTempEdits = false,
		} )


	local doc2OtherClientEditDetailsStream = rxTest:observe(
		LrmLibraryAssetEditInfoImp.getOtherClientEditDetails( { _wfCatalog = fakeWFCatalog }, docId2 ).value		
		-- For ease of testing - lets not do the "time" thing
		:map( function( details )
			details.userUpdatedAsString = details.userUpdatedAsString and type( details.userUpdatedAsString )
			return details
		end )
	)
	-- if there is no feedback document, userName should not be reported

	doc2OtherClientEditDetailsStream:expectDataWithinTime( 1,
		{
			hasTempEdits = false,
		} )

	-- add temp links to each document

	rxTest:waitFor( fakeWFCatalog:docStore():applyOverlay {
		_id = docId1,
		_serverProvidedMetadata = {
			links = {
				[ '/rels/temp/xmp/develop/123456789' ] = {
					develop = {
						userUpdated = "More recently",
						device = "different user device {device-guid-id}",
					},
					uploadedByUser = {
						id = editUserId
					},
				}
			}
		}
	} )

	local userUpdatedNow = KSDate.timeInIso8601Format()

	rxTest:waitFor( fakeWFCatalog:docStore():applyOverlay {
		_id = docId2,
		_serverProvidedMetadata = {
			links = {
				[ '/rels/temp/aux/123456789' ] = {
					develop = {
						userUpdated = userUpdatedNow,
						device = "The newest device {device-guid-id}",
					}
				}
			}
		}
	} )

	-- don't report for other user
	doc1OtherClientEditDetailsStream:expectDataWithinTime( 1,
		{
			hasTempEdits = false,
		} )

	-- report for this user since device is different than
	-- this device
	doc2OtherClientEditDetailsStream:expectDataWithinTime( 1,
		{
			hasTempEdits = true,
			userDeviceWithoutId = "The newest device",
			userUpdatedAsString = 'string',
		} )


	-- Now update the temp link to look like it came from this device
	rxTest:waitFor( fakeWFCatalog:docStore():applyOverlay {
		_id = docId2,
		_serverProvidedMetadata = {
			links = {
				[ '/rels/temp/aux/123456789' ] = {
					develop = {
						userUpdated = userUpdatedNow,
						device = WFDeviceInfo.deviceDescription(),
					}
				}
			}
		}
	} )

	-- don't report hasTempEdits when it's this device
	doc2OtherClientEditDetailsStream:expectDataWithinTime( 1,
		{
			hasTempEdits = false,
		} )


end

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

if WFPlatformInfo.isDesktop then
	return {}
else
	return WFRxTestCase.wrapSuite( 'LrmLibraryAssetEditInfoImpTest', LrmLibraryAssetEditInfoImpTest )
end
