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

WFCatStaleBinaryRemoverTest.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.

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

	-- RxLua
local Rx = require 'Rx'

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

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

	-- WF.oz_client.managed_catalog
local WFCatMockCatalog = require 'WFCatMockCatalog'
local WFCatStaleBinaryRemover = require 'WFCatStaleBinaryRemover'
local WFCatFileSpec = require 'WFCatFileSpec'

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

local WFCatStaleBinaryRemoverTest = {}

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

local mockIdleDownloader = {
	_staleStream = false,
}

function mockIdleDownloader:__init()
	self._staleStream = Rx.Subject()
end

function mockIdleDownloader:clearRecentlyDownloadedStatus( localId, binaryType )
	self._staleStream:onNext( localId, binaryType )
end

function mockIdleDownloader:getStaleStream()
	return self._staleStream
end

local IdleDownloader = Rx.Class 'WFCatIdleDownloader'( mockIdleDownloader )

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

local function basicDocValue( binaryType, realSha256, localCopySha256, isMarkedForOfflineUse )

	local maybeLocalOriginal = binaryType == 'original' and
	{
		master = {
			sha256 = localCopySha256,
			relativePath = 'path/to/original.jpg',
			volumeGuid = 'foo',
			size = 100,
		}
	}
			
	local maybeLocalProxy = binaryType == 'proxy' and 
	{
		[ '2560' ] = {
			sha256 = localCopySha256,
			relativePath = 'path/to/proxy.jpg',
			volumeGuid = 'foo',
			size = 50, 
		},
	}

	return {

		type = 'asset',
		subtype = 'image',
		
		importSource = {
			importTimestamp = "2015-05-26T17:34:23-07:00",
			fileName = "Image.jpg",
			sha256 = realSha256,
		},
		
		_localOnly = {
			isMarkedForOfflineUse = not not isMarkedForOfflineUse,
			files = {
				original = maybeLocalOriginal,
				proxy = maybeLocalProxy
			}
		},

		_serverProvidedMetadata = {
			revision_ids = {
				KSIdGenerator.uuidInLowercaseHex()
			},
			links = {
			
				[ '/rels/master' ] = {
					href = 'path/to/original.jpg',
				},
				[ '/rels/proxy_type/2560' ] = {
					href = 'path/to/proxy.jpg',
				}
			}
		}

	}
	
end

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

local function createAsset( rxTest, wfCatalog, binaryType, isStale, isStaleBecauseOfNoSHA256, isMarkedForOfflineUse )

	local docId = KSIdGenerator.uuidInLowercaseHex()
	
	local realSha256 = KSIdGenerator.uuidInLowercaseHex()
	
	local localCopySha256
	
	if isStale then
		localCopySha256 = KSIdGenerator.uuidInLowercaseHex()
	elseif not isStaleBecauseOfNoSHA256 then
		localCopySha256 = realSha256
	end
	
	local docValue = basicDocValue( binaryType, realSha256, localCopySha256, isMarkedForOfflineUse )
	docValue._id = docId
	
	rxTest:expectSingleValue( wfCatalog:docStore():setDocValue( docValue ), ':ignore:' )
	
	local localId
	
	rxTest:expectSingleValue(
		wfCatalog:docStore():docValue( docId )
			:map( function( docValue )
			
				localId = docValue._localId
				return true
				
			end ), true )
			

	return localId

end

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

local function checkIfRemoved( rxTest, catalog, localId )

	rxTest:expectSingleValue(
		catalog:docStore():docValue( localId )
			:map( function( docValue )
			
				return {
					WFCatFileSpec.getOriginalVolumeGuidFromDocValue( docValue ),
					WFCatFileSpec.getOriginalRelativePathFromDocValue( docValue ),
				}
				
			end ), { nil, nil } )

end

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

local function checkIfPresent( rxTest, catalog, localId )

	rxTest:expectSingleValue(
		catalog:docStore():docValue( localId )
			:map( function( docValue )
			
				return {
					WFCatFileSpec.getOriginalVolumeGuidFromDocValue( docValue ) and true,
					WFCatFileSpec.getOriginalRelativePathFromDocValue( docValue ) and true,
				}
				
			end ), { true, true } )

end

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

function WFCatStaleBinaryRemoverTest.rxTestBasic( rxTest )

	rxTest:setTimeLimit( 10 )

	local wfCatalog = WFCatMockCatalog.createFakeWFCatalog( rxTest )
	
	local stale = true
	
	-- Create Stale Originals
	
	local localId1 = createAsset( rxTest, wfCatalog, 'original', stale )
	createAsset( rxTest, wfCatalog, 'original' )
	local localId3 = createAsset( rxTest, wfCatalog, 'original', stale )
	
	-- Create Stale Proxies
	
	local localId4 = createAsset( rxTest, wfCatalog, 'proxy', stale )
	createAsset( rxTest, wfCatalog, 'proxy' )
	local localId6 = createAsset( rxTest, wfCatalog, 'proxy', stale )
	
	-- Create the mock downloader
	
	local idleDownloader = IdleDownloader()
	
	local staleObserver = rxTest:observe( idleDownloader:getStaleStream() )
		
	-- Create the Binary Remover
	
	local staleBinaryRemover = WFCatStaleBinaryRemover( wfCatalog, idleDownloader )
	
	staleObserver:expectData( localId1, 'original' )
	staleObserver:expectData( localId3, 'original' )
	staleObserver:expectData( localId4, 'proxy' )
	staleObserver:expectData( localId6, 'proxy' )
	
	-- Make sure the assets were removed.
	
	checkIfRemoved( rxTest, wfCatalog, localId1 )
	checkIfRemoved( rxTest, wfCatalog, localId3 )
	checkIfRemoved( rxTest, wfCatalog, localId4 )
	checkIfRemoved( rxTest, wfCatalog, localId6 )
	
	rxTest:finally( function()
	
		staleBinaryRemover:close()
	
	end )
	
end

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

function WFCatStaleBinaryRemoverTest.rxTestStaleBecauseOfNoSha256( rxTest )

	rxTest:setTimeLimit( 10 )

	local wfCatalog = WFCatMockCatalog.createFakeWFCatalog( rxTest )
	
	local stale = true
	
	-- Create Stale Originals
	
	local localId1 = createAsset( rxTest, wfCatalog, 'original', stale )

	-- Create Stale Originals Because of No Local SHA256
	
	local localId2 = createAsset( rxTest, wfCatalog, 'original', false, stale )
	local localId3 = createAsset( rxTest, wfCatalog, 'original', false, stale )
	
	-- Create Non Stale Originals w/ No Local SHA256
	
	local isMarkedForOfflineUse = true
	
	local localId4 = createAsset( rxTest, wfCatalog, 'original', false, stale, isMarkedForOfflineUse )
	local localId5 = createAsset( rxTest, wfCatalog, 'original', false, stale, isMarkedForOfflineUse )
	
	local idleDownloader = IdleDownloader()
	
	local staleObserver = rxTest:observe( idleDownloader:getStaleStream() )
		
	-- Create the Binary Remover
	
	local staleBinaryRemover = WFCatStaleBinaryRemover( wfCatalog, idleDownloader )
	
	staleObserver:expectData( localId1, 'original' )
	staleObserver:expectData( localId2, 'original' )
	staleObserver:expectData( localId3, 'original' )
	
	-- Make sure the stale assets were removed.
	
	checkIfRemoved( rxTest, wfCatalog, localId1 )
	checkIfRemoved( rxTest, wfCatalog, localId2 )
	checkIfRemoved( rxTest, wfCatalog, localId3 )
	
	-- Make sure the non-stale assets were not.
	
	checkIfPresent( rxTest, wfCatalog, localId4 )
	checkIfPresent( rxTest, wfCatalog, localId5 )
	
	rxTest:finally( function()
	
		staleBinaryRemover:close()
	
	end )
	
end

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

return WFRxTestCase.wrapSuite( WFCatStaleBinaryRemoverTest )
