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

WFCatExportTest.lua

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

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

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

	-- If ACR is not supported, disable test before we attempt to
	-- require WFAcr. (That will fail.)
if not require 'WFPlatformInfo'.hasACR then return {} end

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

	-- WF.core.os
local KSPathUtils = require 'KSPathUtils'
local WFFileUtils = require 'WFFileUtils'

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

	-- WF.core.util
local KSTableUtils = require 'KSTableUtils'

	-- WF.oz_client.managed_catalog
local WFCatImport = require 'WFCatImport'
local WFCatExport = require 'WFCatExport'
local WFCatMockCatalog = require 'WFCatMockCatalog'
local MockPixelProviderProcessor = require 'MockPixelProviderProcessor'

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

local createFakeWFCatalog = WFCatMockCatalog.createFakeWFCatalog
local createPixelProcessorStream = MockPixelProviderProcessor.createPixelProcessorStream

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

local testDataPath = KSPathUtils.child( KSPathUtils.getStandardFilePath( 'testdata' ),
										"import-samples" )

local testDataFolder1 = KSPathUtils.child( testDataPath, "folder-1" )

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

local WFCatExportTest = {}
--------------------------------------------------------------------------------

local function importSingleFile( rxTest, wfCatalog, testFilePath )

	local assetId

	rxTest:expectSingleValue(
		WFCatImport.addImageArrayToCatalog( wfCatalog, nil, { {
			filePath = testFilePath,
			width = 2048,
			height = 1024,
			xmpCameraRaw = '<xmp />',
			fileName = KSPathUtils.leafName( testFilePath ),
			fileSize = WFFileUtils.fileAttributes( testFilePath ).fileSize,
			} } )
			:tap( function( result )
				assetId = result.localId
			end ),
		":ignore:" )

	assert( assetId, "Docstore didn't fire doc change. Maybe import didnt succeed." )

	return assetId
end

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

function WFCatExportTest.rxTestExportOneAssetOriginal( rxTest )

	rxTest:setTimeLimit( 15 )
	
	local exportPath = KSPathUtils.child( KSPathUtils.getStandardFilePath( 'temp' ), 'TestExportOneAssetOriginal' )
	pcall ( WFFileUtils.mkdir, exportPath )

	rxTest:finally( function()
		WFFileUtils.delete( exportPath )
	end )


	local wfCatalog = createFakeWFCatalog( rxTest )
	local testFilePath = KSPathUtils.child( testDataFolder1, "IMG_7763.jpg" )
	local assetId = importSingleFile( rxTest, wfCatalog, testFilePath )

	local settings = 
		{
			format = 'original',
			plainOriginal = true,
			destinationFolder = exportPath,
		}
	
	local outFilePath = KSPathUtils.child( settings.destinationFolder, "IMG_7763.jpg" )
	
	local exportTask = WFCatExport.exportAssetsFromCatalog( 
		wfCatalog, createPixelProcessorStream( rxTest, wfCatalog ), 
		nil, { assetId }, settings, {} )
	local exportProgress = exportTask:status()
	local loggingSubscription = exportProgress:subscribe( function( data )
		debug.print()
	end)
	
	local progress = rxTest:observe( exportProgress )
	
	progress:expectDataWithinTime( 5,
		{
			processedCount = 0,
			description = "Exporting files",
			errorCount = 0,
			percentComplete = 0,
			totalCount = 1,
		} )
	
	progress:expectDataWithinTime( 5,
		{
			processedCount = 1,
			description = "Exporting files",
			errorCount = 0,
			percentComplete = 1,
			totalCount = 1,
			extraInfo = {
				id = assetId,
				success = true,
				data = {
					path = outFilePath,
				}
			}
		} )

	progress:expectCompleted()
	
	rxTest:expectEqual( 'file', WFFileUtils.exists( outFilePath ) )
	local testFileSize = KSTableUtils.derefOpt( WFFileUtils.fileAttributes( testFilePath ),
											'fileSize' )

	local exportedfileSize = KSTableUtils.derefOpt( WFFileUtils.fileAttributes( outFilePath ),
											'fileSize' )

	rxTest:expectEqual( testFileSize, exportedfileSize )
	exportTask:dispose()
	loggingSubscription:dispose()
	
end

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

function WFCatExportTest.rxTestExportManyAssetOriginal( rxTest )

	rxTest:setTimeLimit( 15 )
	
	local exportPath = KSPathUtils.child( KSPathUtils.getStandardFilePath( 'temp' ), 'TestExportManyAssetOriginal' )
	pcall ( WFFileUtils.mkdir, exportPath )
	
	rxTest:finally( function()
		WFFileUtils.delete( exportPath )
	end )

	local testFilePath1 = KSPathUtils.child( testDataFolder1, "IMG_7706.PNG" )
	local testFilePath2 = KSPathUtils.child( testDataFolder1, "IMG_7763.jpg" )
	local testFilePath3 = KSPathUtils.child( testDataFolder1, "IMG_7766.jpg" )
	local testFilePath4 = KSPathUtils.child( testDataFolder1, "IMG_9876.CR2" )
	local testFilePath5 = KSPathUtils.child( testDataFolder1, "ir-trees.dng" )
	local testFilePath6 = KSPathUtils.child( testDataFolder1, "NikonPhotoworldSafariMiami281.NEF" )

	local wfCatalog = createFakeWFCatalog( rxTest )

	local assetId1 = importSingleFile( rxTest, wfCatalog, testFilePath1 )
	local assetId2 = importSingleFile( rxTest, wfCatalog, testFilePath2 )
	local assetId3 = importSingleFile( rxTest, wfCatalog, testFilePath3 )
	local assetId4 = importSingleFile( rxTest, wfCatalog, testFilePath4 )
	local assetId5 = importSingleFile( rxTest, wfCatalog, testFilePath5 )
	local assetId6 = importSingleFile( rxTest, wfCatalog, testFilePath6 )

	local assetIds = { assetId1, assetId2, assetId3, assetId4, assetId5, assetId6 }
	
	local settings = {
		format = 'original',
		destinationFolder = exportPath,
	}
	
	local exportTask = WFCatExport.exportAssetsFromCatalog( 
		wfCatalog, createPixelProcessorStream( rxTest, wfCatalog ), nil, assetIds, settings, {} )
	local exportProgress = exportTask:status()
	local progress = rxTest:observe(
		exportProgress:map(
			function(status)
				status.extraInfo = nil
				return status
			end) ) 
	
	progress:expectDataWithinTime( 5,
		{
			processedCount = 0,
			description = "Exporting files",
			errorCount = 0,
			percentComplete = 0,
			totalCount = 6,
		} )
	
	progress:expectDataWithinTime( 5,
		{
			processedCount = 6,
			description = "Exporting files",
			errorCount = 0,
			percentComplete = 1,
			totalCount = 6,
		} )
	progress:expectCompleted()
	exportTask:dispose()

end

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

function WFCatExportTest.rxTestCheckAndReclaimSpace( rxTest )

	rxTest:setTimeLimit( 15 )
	
	local exportPath = KSPathUtils.child( KSPathUtils.getStandardFilePath( 'temp' ), rxTest:testName() )
	pcall ( WFFileUtils.mkdir, exportPath )

	rxTest:finally( function()
		WFFileUtils.delete( exportPath )
	end )

	local wfCatalog = createFakeWFCatalog( rxTest )
	
	local assetIds = { 123, 345 }
	local settings = {
		format = 'original',
		destinationFolder = exportPath,
	}
	
	-- Test same disk, has enough space
	local downloadNeededSizeResultMap = {}
	downloadNeededSizeResultMap[ assetIds[ 1 ] ] = { true, 1000 }
	downloadNeededSizeResultMap[ assetIds[ 2 ] ] = { true, 450 }
	
	local fileSystemResultMap = {}
	fileSystemResultMap[ wfCatalog:fileSpec():rootPath() ] = {
		fileSystemNumber = 111,
		fileSystemFreeSize = 4000,
	}
	fileSystemResultMap[ exportPath ] = {
		fileSystemNumber = 111,
		fileSystemFreeSize = 4000,
	}
	
	WFCatExport.setUpTestFunctions( downloadNeededSizeResultMap, fileSystemResultMap )
	
	local checkAndReclaimSpaceObservable = WFCatExport.checkAndReclaimSpace( wfCatalog, assetIds, settings )
	
	rxTest:observe( checkAndReclaimSpaceObservable )
		:expectDataWithinTime( 5, { 0, 0 } )
	
	
	-- Test same disk, not enough space
	downloadNeededSizeResultMap = {}
	downloadNeededSizeResultMap[ assetIds[ 1 ] ] = { true, 1000 }
	downloadNeededSizeResultMap[ assetIds[ 2 ] ] = { true, 450 }
	
	fileSystemResultMap = {}
	fileSystemResultMap[ wfCatalog:fileSpec():rootPath() ] = {
		fileSystemNumber = 111,
		fileSystemFreeSize = 1100,
	}
	fileSystemResultMap[ exportPath ] = {
		fileSystemNumber = 111,
		fileSystemFreeSize = 1100,
	}
	
	WFCatExport.setUpTestFunctions( downloadNeededSizeResultMap, fileSystemResultMap )
	
	checkAndReclaimSpaceObservable = WFCatExport.checkAndReclaimSpace( wfCatalog, assetIds, settings )
	
	rxTest:observe( checkAndReclaimSpaceObservable )
		:expectDataWithinTime( 5, { ( 2900 - 1100 ), 0 } )
	
	
	-- Test different disk, not enough space
	downloadNeededSizeResultMap = {}
	downloadNeededSizeResultMap[ assetIds[ 1 ] ] = { true, 1000 }
	downloadNeededSizeResultMap[ assetIds[ 2 ] ] = { true, 450 }
	
	fileSystemResultMap = {}
	fileSystemResultMap[ wfCatalog:fileSpec():rootPath() ] = {
		fileSystemNumber = 111,
		fileSystemFreeSize = 1100,
	}
	fileSystemResultMap[ exportPath ] = {
		fileSystemNumber = 222,
		fileSystemFreeSize = 150,
	}
	
	WFCatExport.setUpTestFunctions( downloadNeededSizeResultMap, fileSystemResultMap )
	
	checkAndReclaimSpaceObservable = WFCatExport.checkAndReclaimSpace( wfCatalog, assetIds, settings )
	
	rxTest:observe( checkAndReclaimSpaceObservable )
		:expectDataWithinTime( 5, { ( 1450 - 1100 ), ( 1450 - 150 ) } )
		
		
	-- Test different disk, not enough space, no download needed
	downloadNeededSizeResultMap = {}
	downloadNeededSizeResultMap[ assetIds[ 1 ] ] = { false, 1000 }
	downloadNeededSizeResultMap[ assetIds[ 2 ] ] = { false, 450 }
	
	fileSystemResultMap = {}
	fileSystemResultMap[ wfCatalog:fileSpec():rootPath() ] = {
		fileSystemNumber = 111,
		fileSystemFreeSize = 1100,
	}
	fileSystemResultMap[ exportPath ] = {
		fileSystemNumber = 222,
		fileSystemFreeSize = 150,
	}
	
	WFCatExport.setUpTestFunctions( downloadNeededSizeResultMap, fileSystemResultMap )
	
	checkAndReclaimSpaceObservable = WFCatExport.checkAndReclaimSpace( wfCatalog, assetIds, settings )
	
	rxTest:observe( checkAndReclaimSpaceObservable )
		:expectDataWithinTime( 5, { 0, ( 1450 - 150 ) } )
end

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

function WFCatExportTest.rxTestExportOneAssetCustomFilename( rxTest )

	rxTest:setTimeLimit( 15 )
	
	local exportPath = KSPathUtils.child( KSPathUtils.getStandardFilePath( 'temp' ), 'TestExportOneAssetOriginal' )
	pcall ( WFFileUtils.mkdir, exportPath )

	rxTest:finally( function()
		WFFileUtils.delete( exportPath )
	end )

	local wfCatalog = createFakeWFCatalog( rxTest )
	local testFilePath = KSPathUtils.child( testDataFolder1, "IMG_7763.jpg" )
	local assetId = importSingleFile( rxTest, wfCatalog, testFilePath )
	
	local settings = 
		{
			format = 'original',
			plainOriginal = true,
			destinationFolder = exportPath,
		}
	
	local outFilePath = KSPathUtils.child( settings.destinationFolder, "CustomName.jpg" )
	
	local extraSettingsByAssetId = {}
	extraSettingsByAssetId[ assetId ] = {
		outputFileName = "CustomName.jpg"
	}
	local exportTask = WFCatExport.exportAssetsFromCatalog( 
		wfCatalog, createPixelProcessorStream( rxTest, wfCatalog ), 
		nil, { assetId }, settings, extraSettingsByAssetId )
	local exportProgress = exportTask:status()
	local loggingSubscription = exportProgress:subscribe( function( data )
		debug.print()
	end)
	
	local progress = rxTest:observe( exportProgress )
	
	progress:expectDataWithinTime( 5,
		{
			processedCount = 0,
			description = "Exporting files",
			errorCount = 0,
			percentComplete = 0,
			totalCount = 1,
		} )
	
	progress:expectDataWithinTime( 5,
		{
			processedCount = 1,
			description = "Exporting files",
			errorCount = 0,
			percentComplete = 1,
			totalCount = 1,
			extraInfo = {
				id = assetId,
				success = true,
				data = {
					path = outFilePath,
				}
			}
		} )

	progress:expectCompleted()
	
	rxTest:expectEqual( 'file', WFFileUtils.exists( outFilePath ) )
	local testFileSize = KSTableUtils.derefOpt( WFFileUtils.fileAttributes( testFilePath ),
											'fileSize' )

	local exportedfileSize = KSTableUtils.derefOpt( WFFileUtils.fileAttributes( outFilePath ),
											'fileSize' )

	rxTest:expectEqual( testFileSize, exportedfileSize )
	exportTask:dispose()
	loggingSubscription:dispose()
	
end

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

return WFRxTestCase.wrapSuite( WFCatExportTest )
