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

NmbPurgeDbUpdaterTest.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'
local WFCatMockCatalog = require 'WFCatMockCatalog'

	-- WF.core.utils
local KSPathUtils = require 'KSPathUtils'
local WFFileUtils = require 'WFFileUtils'
local KSIdGenerator = require 'KSIdGenerator'

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

local NmbPurgeDbUpdaterTest = {}

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

local basePath = KSPathUtils.getStandardFilePath( 'carouselDocuments' )
local volumeGuid = WFFileUtils.getVolumeGuidForPath( basePath )

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

local function mapAwayDate( tbl )

	local mappedTbl = {}

	for k, v in pairs( tbl ) do 
		
		if type( v ) == 'table' then
			mappedTbl[ k ] = mapAwayDate( v )
		elseif k ~= 'lastAccessed' then
			mappedTbl[ k ] = v
		else
			mappedTbl[ k ] = '<value>'
		end
		
	end
	
	return mappedTbl

end

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

local function createBasicDoc( rxTest, wfCatalog )
	
	local docId = KSIdGenerator.uuidInLowercaseHex()
	local localId
	
	local docValue = {

		_id = docId,
		type = 'asset',
		subtype = 'image',
		captureDate = '2012-08-15T15:22:29',
		importSource = {
			importTimestamp = "2015-05-26T17:34:23-07:00",
			fileName = "Image.jpg",
		},
	}
	
	rxTest:expectSingleValue( wfCatalog:docStore():setDocValue( docValue ), ':ignore:' )

	rxTest:expectSingleValue(
		wfCatalog:docStore():docValue( docId )
			:map( function( docValue )
				localId = docValue._localId
				return true
			end ), true )

	return docId, localId

end

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

function NmbPurgeDbUpdaterTest.rxTestBasic( rxTest )

	rxTest:setTimeLimit( 10 )

	local wfCatalog = WFCatMockCatalog.createFakeWFCatalog( rxTest )

	rxTest:finally( function()
	
		wfCatalog:close()
	
	end )

	local mruDatabase = wfCatalog:mruDatabase()

	local docId, localId = createBasicDoc( rxTest, wfCatalog )

	rxTest:expectSingleValue( mruDatabase:waitUntilUpToDate(), true )

	local fileAccessDump = mruDatabase:DEBUG_dumpLastAccessContents()
	
	local expectedDump = {
		{
			docId = docId,
			lastAccessed = '<value>',
			isImportant = 0,
			localId = localId,
			ozHasOriginal = 0,
			ozHasProxy = 0,
			originalFileSize = 0,
			proxyFileSize = 0,
			sufficientRenditionFoundOnOz = 0,
			xmpSidecarSize = 0,
		},
	}
	
	rxTest:expectSingleValue( fileAccessDump:map( mapAwayDate ), expectedDump )
	
	-- Make the asset important.
	
	rxTest:expectSingleValue( wfCatalog:docStore():applyOverlay( {
		_id = localId,
			_localOnly = {
				isMarkedForOfflineUse = true
			},
		} ), ':ignore:' )
	
	rxTest:expectSingleValue( mruDatabase:waitUntilUpToDate(), true )

	fileAccessDump = mruDatabase:DEBUG_dumpLastAccessContents()
	
	expectedDump = {
		{
			docId = docId,
			lastAccessed = '<value>',
			isMarkedForOfflineUse = 1,
			isImportant = 1,
			localId = localId,
			ozHasOriginal = 0,
			ozHasProxy = 0,
			originalFileSize = 0,
			proxyFileSize = 0,
			sufficientRenditionFoundOnOz = 0,
			xmpSidecarSize = 0,
		},
	}
	
	rxTest:expectSingleValue( fileAccessDump:map( mapAwayDate ), expectedDump )
	
	-- Make the asset unimportant.
	
	rxTest:expectSingleValue( wfCatalog:docStore():applyOverlay( {
		_id = localId,
			_localOnly = {
				isMarkedForOfflineUse = false
			},
		} ), ':ignore:' )
	
	rxTest:expectSingleValue( mruDatabase:waitUntilUpToDate(), true )

	fileAccessDump = mruDatabase:DEBUG_dumpLastAccessContents()
	
	expectedDump = {
		{
			docId = docId,
			lastAccessed = '<value>',
			isMarkedForOfflineUse = 0,
			isImportant = 0,
			localId = localId,
			ozHasOriginal = 0,
			ozHasProxy = 0,
			originalFileSize = 0,
			proxyFileSize = 0,
			sufficientRenditionFoundOnOz = 0,
			xmpSidecarSize = 0,
		},
	}
	
	rxTest:expectSingleValue( fileAccessDump:map( mapAwayDate ), expectedDump )
	
	-- Add local negatives
	
	local localOnly = {
		files = {
			original = {},
			proxy = {}
		},
	}
	
	localOnly.files.original.master = {
			relativePath = 'i am an original',
			volumeGuid = volumeGuid
	}
	
	localOnly.files.proxy[ '2560' ] = {
		relativePath = 'i am a proxy',
		volumeGuid = volumeGuid
	}
	
	rxTest:expectSingleValue( wfCatalog:docStore():applyOverlay( {
		_id = localId,
			_localOnly = localOnly
		} ), ':ignore:' )
	
	rxTest:expectSingleValue( mruDatabase:waitUntilUpToDate(), true )

	fileAccessDump = mruDatabase:DEBUG_dumpLastAccessContents()
	
	expectedDump = {
		{	
			docId = docId,
			lastAccessed = '<value>',
			isMarkedForOfflineUse = 0,
			isImportant = 0,
			localId = localId,
			ozHasOriginal = 0,
			ozHasProxy = 0,
			volumeGuidUsedByOriginal = volumeGuid,
			volumeGuidUsedByProxy = volumeGuid,
			originalFileSize = 0,
			proxyFileSize = 0,
			sufficientRenditionFoundOnOz = 0,
			xmpSidecarSize = 0,
		},
	}
	
	rxTest:expectSingleValue( fileAccessDump:map( mapAwayDate ), expectedDump )
	
	-- Remove local negatives
	
	localOnly = {
		files = {
			original = { _delete = true },
			proxy = { _delete = true }
		},
	}
	
	rxTest:expectSingleValue( wfCatalog:docStore():applyOverlay( {
		_id = localId,
			_localOnly = localOnly
		} ), ':ignore:' )
	
	rxTest:expectSingleValue( mruDatabase:waitUntilUpToDate(), true )

	fileAccessDump = mruDatabase:DEBUG_dumpLastAccessContents()
	
	expectedDump = {
		{
			docId = docId,
			lastAccessed = '<value>',
			isMarkedForOfflineUse = 0,
			isImportant = 0,
			localId = localId,
			ozHasOriginal = 0,
			ozHasProxy = 0,
			originalFileSize = 0,
			proxyFileSize = 0,
			sufficientRenditionFoundOnOz = 0,
			xmpSidecarSize = 0,
		},
	}
	
	rxTest:expectSingleValue( fileAccessDump:map( mapAwayDate ), expectedDump )
	
	-- Add Size Info
	
	localOnly = {
		files = {
			original = {},
			proxy = {}
		},
	}
	
	localOnly.files.original.master = { size = 10 }
	localOnly.files.proxy[ '2560' ] = { size = 5 }
	
	rxTest:expectSingleValue( wfCatalog:docStore():applyOverlay( {
		_id = localId,
			_localOnly = localOnly
		} ), ':ignore:' )
	
	rxTest:expectSingleValue( mruDatabase:waitUntilUpToDate(), true )

	fileAccessDump = mruDatabase:DEBUG_dumpLastAccessContents()
	
	expectedDump = {
		{
			docId = docId,
			lastAccessed = '<value>',
			isMarkedForOfflineUse = 0,
			isImportant = 0,
			localId = localId,
			ozHasOriginal = 0,
			ozHasProxy = 0,
			originalFileSize = 10,
			proxyFileSize = 5, 
			sufficientRenditionFoundOnOz = 0,
			xmpSidecarSize = 0,
		},
	}
	
	rxTest:expectSingleValue( fileAccessDump:map( mapAwayDate ), expectedDump )
	
	-- Add Oz Status Info
	
	local links = {}
	
	links[ '/rels/proxy_type/2560' ] = { href = '/proxy/href/bogus/testing' } 
	links[ '/rels/master' ] = { href = '/master/href/bogus/testing' }
	
	rxTest:expectSingleValue( wfCatalog:docStore():applyOverlay( {
		_id = localId,
			_serverProvidedMetadata = {
				links = links
			}
		} ), ':ignore:' )
	
	rxTest:expectSingleValue( mruDatabase:waitUntilUpToDate(), true )

	fileAccessDump = mruDatabase:DEBUG_dumpLastAccessContents()
	
	expectedDump = {
		{
			docId = docId,
			lastAccessed = '<value>',
			isMarkedForOfflineUse = 0,
			isImportant = 0,
			localId = localId,
			ozHasOriginal = 1,
			ozHasProxy = 1,
			originalFileSize = 10,
			proxyFileSize = 5,
			sufficientRenditionFoundOnOz = 0,
			xmpSidecarSize = 0,
		},
	}
	
	rxTest:expectSingleValue( fileAccessDump:map( mapAwayDate ), expectedDump )
	
	-- Remove the oz links
	
	links = { _delete = true }
	
	rxTest:expectSingleValue( wfCatalog:docStore():applyOverlay( {
		_id = localId,
			_serverProvidedMetadata = {
				links = links
			}
		} ), ':ignore:' )
	
	rxTest:expectSingleValue( mruDatabase:waitUntilUpToDate(), true )

	fileAccessDump = mruDatabase:DEBUG_dumpLastAccessContents()
	
	expectedDump = {
		{
			docId = docId,
			lastAccessed = '<value>',
			isMarkedForOfflineUse = 0,
			isImportant = 0,
			localId = localId,
			ozHasOriginal = 0,
			ozHasProxy = 0,
			originalFileSize = 10,
			proxyFileSize = 5,
			sufficientRenditionFoundOnOz = 0,
			xmpSidecarSize = 0,
		},
	}
	
	rxTest:expectSingleValue( fileAccessDump:map( mapAwayDate ), expectedDump )

	-- Add Oz Rendition Links to verify behavior of sufficientRenditionFoundOnOz

	-- thumbnail and thumbnail2x are not considered a sufficient rendition.
	links = {}
	links[ '/rels/rendition_type/thumbnail' ] = { href = '/rendition/href/bogus/testing' }
	links[ '/rels/rendition_type/thumbnail2x' ] = { href = '/rendition/href/bogus/testing' }

	rxTest:expectSingleValue( wfCatalog:docStore():applyOverlay( {
		_id = localId,
			_serverProvidedMetadata = {
				links = links
			}
		} ), ':ignore:' )

	rxTest:expectSingleValue( mruDatabase:waitUntilUpToDate(), true )

	fileAccessDump = mruDatabase:DEBUG_dumpLastAccessContents()

	expectedDump = {
		{
			docId = docId,
			lastAccessed = '<value>',
			isMarkedForOfflineUse = 0,
			isImportant = 0,
			localId = localId,
			ozHasOriginal = 0,
			ozHasProxy = 0,
			originalFileSize = 10,
			proxyFileSize = 5,
			sufficientRenditionFoundOnOz = 0,
			xmpSidecarSize = 0,
		},
	}

	rxTest:expectSingleValue( fileAccessDump:map( mapAwayDate ), expectedDump )

	-- A 640 pixel rendition is considered sufficient.
	links[ '/rels/rendition_type/640' ] = { href = '/rendition/href/bogus/testing' }

	rxTest:expectSingleValue( wfCatalog:docStore():applyOverlay( {
		_id = localId,
			_serverProvidedMetadata = {
				links = links
			}
		} ), ':ignore:' )

	rxTest:expectSingleValue( mruDatabase:waitUntilUpToDate(), true )

	fileAccessDump = mruDatabase:DEBUG_dumpLastAccessContents()

	expectedDump = {
		{
			docId = docId,
			lastAccessed = '<value>',
			isMarkedForOfflineUse = 0,
			isImportant = 0,
			localId = localId,
			ozHasOriginal = 0,
			ozHasProxy = 0,
			originalFileSize = 10,
			proxyFileSize = 5,
			sufficientRenditionFoundOnOz = 1,
			xmpSidecarSize = 0,
		},
	}

	rxTest:expectSingleValue( fileAccessDump:map( mapAwayDate ), expectedDump )

end

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

local function createBasicAlbumDoc( rxTest, wfCatalog )
	
	local docId = KSIdGenerator.uuidInLowercaseHex()
	local localId
	
	local docValue = {

		_id = docId,
		type = 'album',
		subtype = 'collection',
		name = 'test 1',
		story = {
			title = 'Title Test 1'
		}
	}
	
	rxTest:expectSingleValue( wfCatalog:docStore():setDocValue( docValue ), ':ignore:' )

	rxTest:expectSingleValue(
		wfCatalog:docStore():docValue( docId )
			:map( function( docValue )
				localId = docValue._localId
				return true
			end ), true )

	return docId, localId

end

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

function NmbPurgeDbUpdaterTest.rxTest_WF813_Bug( rxTest )

	rxTest:setTimeLimit( 10 )

	local wfCatalog = WFCatMockCatalog.createFakeWFCatalog( rxTest )

	rxTest:finally( function()
	
		wfCatalog:close()
	
	end )

	local mruDatabase = wfCatalog:mruDatabase()

	local docId1, localId1 = createBasicDoc( rxTest, wfCatalog )

	rxTest:expectSingleValue( mruDatabase:waitUntilUpToDate(), true )

	createBasicAlbumDoc( rxTest, wfCatalog )
		-- Non-Asset docs should not cause the NmbPurgeDbUpdater to
		-- fail to update the change counter. 
		
	rxTest:expectSingleValue( mruDatabase:waitUntilUpToDate(), true )

	local fileAccessDump = mruDatabase:DEBUG_dumpLastAccessContents()
	
	local expectedDump = {
		{
			docId = docId1,
			lastAccessed = '<value>',
			isImportant = 0,
			localId = localId1,
			ozHasOriginal = 0,
			ozHasProxy = 0,
			originalFileSize = 0,
			proxyFileSize = 0,
			sufficientRenditionFoundOnOz = 0,
			xmpSidecarSize = 0,
		},
	}
	
	rxTest:expectSingleValue( fileAccessDump:map( mapAwayDate ), expectedDump )
	
end

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

return WFRxTestCase.wrapSuite( NmbPurgeDbUpdaterTest )
