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

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

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

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

--------------------------------------------------------------------------------
	-- RxLua
local Rx = require 'Rx'
local Observable = Rx.Observable

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

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

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

	-- WF.oz_client.managed_catalog
local WFCatImport = require 'WFCatImport'
local WFCatExportOriginalProvider = require 'WFCatExportOriginalProvider'
local WFCatExportPixelProviderTask = require 'WFCatExportPixelProviderTask'
local WFCatMockCatalog = require 'WFCatMockCatalog'
local MockPixelProviderProcessor = require 'MockPixelProviderProcessor'
local WFCatFileSpec = require 'WFCatFileSpec'

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

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 function sanitizeError( err )
	return err and err:match( '[_%w]+$' )
end

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

local WFCatExportOriginalProviderTest = {}

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

local function importSingleFile( rxTest, testFilePath, sidecarPath )

	local assetId

	local wfCatalog = createFakeWFCatalog( rxTest )

	local additionalInfo
	if sidecarPath then
		additionalInfo = {
			XMPSideCarPath = sidecarPath
		}
	end

	rxTest:expectSingleValue(
		WFCatImport.addImageArrayToCatalog( wfCatalog, nil, { {
			additionalInfo = additionalInfo,
			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 wfCatalog, assetId
end


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

function WFCatExportOriginalProviderTest.rxTestExportOriginalCR2( rxTest )

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

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

	local testFilePath = KSPathUtils.child( testDataFolder1, "IMG_9876.CR2" )
	local wfCatalog, assetId = importSingleFile( rxTest, testFilePath )

	local request = {
		id = assetId,
		settings = {
			format = 'original',
			destinationFolder = exportPath,
		},
	}
	
	local exportResult
	
	local pixelPathProcessorStream = createPixelProcessorStream( rxTest, wfCatalog )
	local exportPixelProviderTask = WFCatExportPixelProviderTask( pixelPathProcessorStream )
	rxTest:expectSingleValue(
		WFCatExportOriginalProvider:exportAsset( request, wfCatalog, exportPixelProviderTask )
			:tap( function( data ) 
				exportResult = data
			end),
		':ignore:' )
	
	
	rxTest:expectEqual( 'table', type( exportResult ) )
	
	local outFilePath = exportResult.path
	rxTest:expectEqual( KSPathUtils.child( request.settings.destinationFolder, "IMG_9876.CR2" ), outFilePath )
	rxTest:expectEqual( 'file', WFFileUtils.exists( outFilePath ) )

	-- Sidecar file now generated by client side code via cr_sdk

end

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

local function createSidecarFile( rxTest, pathToSaveTo, creatorToolName )

	local KSData = require 'KSData'
	local WFXmp = require 'WFXmp'
	local WFXMLNS = require 'WFXMLNS'

	local sidecarMetadata = WFXmp.WFXmp()

	-- modified items
	sidecarMetadata:set( WFXMLNS.xap, "ModifyDate", "2020-12-12T11:10:09.876Z" )
	sidecarMetadata:set( WFXMLNS.xap, "Rating", 1 )

	-- added item
	sidecarMetadata:set( WFXMLNS.xap, "CreatorTool", creatorToolName )

	local sidecarData = sidecarMetadata:serialize()
	KSData.saveToFile( sidecarData, pathToSaveTo )

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

end

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

function WFCatExportOriginalProviderTest.rxTestExportOriginalWithImportedSidecarCR2( rxTest )

	rxTest:setTimeLimit( 10 )

	local testName = rxTest:testName()

	-- copy import file to a location we can create a side car file in.
	local testFilePath = KSPathUtils.child( testDataFolder1, "IMG_9876.CR2" )
	local importFolder = WFTestFileUtils.createTestFolder( rxTest, testName .. '_source' )
	local importFilePath = KSPathUtils.child( importFolder, 'IMG_9876.CR2' )
	WFFileUtils.copy( testFilePath, importFilePath )
	local importSidecarPath = KSPathUtils.child( importFolder, 'IMG_9876.XMP' )

	local creatorToolName = rxTest:testName()
	createSidecarFile( rxTest, importSidecarPath, creatorToolName )

	local exportPath = WFTestFileUtils.createTestFolder( rxTest, testName .. '_export' )

	local wfCatalog, assetId = importSingleFile( rxTest, importFilePath, importSidecarPath )

	local request = {
		id = assetId,
		settings = {
			format = 'original',
			destinationFolder = exportPath,
		},
	}

	local exportResult

	local pixelPathProcessorStream = createPixelProcessorStream( rxTest, wfCatalog )
	local exportPixelProviderTask = WFCatExportPixelProviderTask( pixelPathProcessorStream )
	rxTest:expectSingleValue(
		WFCatExportOriginalProvider:exportAsset( request, wfCatalog, exportPixelProviderTask )
			:tap( function( data )
				exportResult = data
			end),
		':ignore:' )

	rxTest:expectEqual( 'table', type( exportResult ) )
	
	local outFilePath = exportResult.path
	rxTest:expectEqual( KSPathUtils.child( request.settings.destinationFolder, "IMG_9876.CR2" ), outFilePath )
	rxTest:expectEqual( 'file', WFFileUtils.exists( outFilePath ) )
	
	-- Sidecar file now generated by client side code via cr_sdk

end

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

function WFCatExportOriginalProviderTest.rxTestExportOriginalDNG( rxTest )

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

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

	local testFilePath = KSPathUtils.child( testDataFolder1, "ir-trees.dng" )
	local wfCatalog, assetId = importSingleFile( rxTest, testFilePath )
	
	local request = {
		id = assetId,
		settings = {
			format = 'original',
			destinationFolder = exportPath,
		},
	}
	
	local exportResult
	
	local pixelPathProcessorStream = createPixelProcessorStream( rxTest, wfCatalog )
	local exportPixelProviderTask = WFCatExportPixelProviderTask( pixelPathProcessorStream )
	rxTest:expectSingleValue(
		WFCatExportOriginalProvider:exportAsset( request, wfCatalog, exportPixelProviderTask )
			:tap( function( data ) 
				exportResult = data
			end),
		':ignore:' )
	
	
	rxTest:expectEqual( 'table', type( exportResult ) )
	
	local outFilePath = exportResult.path
	rxTest:expectEqual( KSPathUtils.child( request.settings.destinationFolder, "ir-trees.dng" ), outFilePath )
	rxTest:expectEqual( 'file', WFFileUtils.exists( outFilePath ) )
	
	rxTest:expectEqual( nil, exportResult.sidecarPath )
	
	
end


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

function WFCatExportOriginalProviderTest.rxTestExportOriginalCustomFilename( rxTest )

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

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

	local testFilePath = KSPathUtils.child( testDataFolder1, "ir-trees.dng" )
	local wfCatalog, assetId = importSingleFile( rxTest, testFilePath )

	local request = {
		id = assetId,
		settings = {
			format = 'original',
			destinationFolder = exportPath,
		},
		fileName = "CustomName.dng"
	}
	
	local exportResult
	
	local pixelPathProcessorStream = createPixelProcessorStream( rxTest, wfCatalog )
	local exportPixelProviderTask = WFCatExportPixelProviderTask( pixelPathProcessorStream )
	rxTest:expectSingleValue(
		WFCatExportOriginalProvider:exportAsset( request, wfCatalog, exportPixelProviderTask )
			:tap( function( data ) 
				exportResult = data
			end),
		':ignore:' )
	
	
	rxTest:expectEqual( 'table', type( exportResult ) )
	
	local outFilePath = exportResult.path
	rxTest:expectEqual( KSPathUtils.child( request.settings.destinationFolder, "CustomName.dng" ), outFilePath )
	rxTest:expectEqual( 'file', WFFileUtils.exists( outFilePath ) )
	
end

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

function WFCatExportOriginalProviderTest.rxTestExportMissingOriginal( rxTest )

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

	rxTest:finally( function()
		WFFileUtils.delete( exportPath )
	end )
	
	local testFilePath = KSPathUtils.child( testDataFolder1, "ir-trees.dng" )
	local wfCatalog, assetId = importSingleFile( rxTest, testFilePath )
	
	-- Delete the original link entry
	rxTest:expectSingleValue(
		wfCatalog:docStore():docValue( assetId )
			:flatMap( function( docValue )
			
				local volumeGuid = KSTableUtils.derefOpt( docValue, "_localOnly", "files", "original", "master", "volumeGuid" )
				
				local originalPath = WFCatFileSpec.buildOriginalPathFromDocValue( docValue )
				local localProxyPath = wfCatalog:fileSpec():pathForProxy( docValue._id, "2560" )
				WFFileUtils.copy( originalPath, localProxyPath )
				
				WFFileUtils.delete( originalPath )
				
				return wfCatalog:docStore():applyOverlay {
					_id = assetId,
					_localOnly = {
						files = {
							original = { _delete = true },
							proxy = {
								['2560'] = {
									relativePath = WFFileUtils.removeVolumeFromPath( localProxyPath ),
									volumeGuid = volumeGuid,
								},
							}
						}
					},
				}
				
			end ),
		':ignore:' )
	
	
	-- fallbackToProxySize not set
	local settings = {
		format = 'original',
		destinationFolder = exportPath,
		longEdge = 'custom',
		customMaxSize = 200,
	}
	
	local request = {
		id = assetId,
		settings = settings,
	}
	
	local exportResult, err
	
	local pixelPathProcessorStream = createPixelProcessorStream( rxTest, wfCatalog )
	local exportPixelProviderTask = WFCatExportPixelProviderTask( pixelPathProcessorStream )
	rxTest:expectSingleValue(
		WFCatExportOriginalProvider:exportAsset( request, wfCatalog, exportPixelProviderTask )
			:tap( function( data ) 
				exportResult = data
			end)
			:catch( function( errorString ) 
				err = sanitizeError( errorString )
				return Observable.just( {} )
			end),
		':ignore:' )
	
	rxTest:expectEqual( nil, exportResult )
	rxTest:expectEqual( 'original_unavailable', err )
	
	
	-- Use proxy for exporting
	
	settings = {
		format = 'original',
		destinationFolder = exportPath,
		longEdge = 'custom',
		customMaxSize = 200,
		fallbackToProxySize = true,
	}
	
	request = {
		id = assetId,
		settings = settings,
	}
	
	rxTest:expectSingleValue(
		WFCatExportOriginalProvider:exportAsset( request, wfCatalog, exportPixelProviderTask )
			:tap( function( data ) 
				exportResult = data
			end)
			:catch( function( errorString ) 
				err = sanitizeError( errorString )
				return Observable.just( {} )
			end),
		':ignore:' )
	
	rxTest:expectEqual( 'table', type( exportResult ) )
	
	local outFilePath = exportResult.path
	rxTest:expectEqual( 'file', WFFileUtils.exists( outFilePath ) )

end

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

return WFRxTestCase.wrapSuite( WFCatExportOriginalProviderTest )
