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

PixelPathProviderSchedulerFullRunTest.lua

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

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

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

--==============================================================================
-- Skip all tests logic
--==============================================================================

-- This test uses ACR since it renders, if a platform doesn't have ACR the test
-- will fail to even load. We therefore bail in that case.
local WFPlatformInfo = require 'WFPlatformInfo'

if not WFPlatformInfo.hasACR then return {} end

-- TODO 2015.11.02 bkruse
-- rxTestChooseRenditionStrategy and rxTestPixelCacheCheckTask are failing on
-- Android, too busy to figure out why right now.
if WFPlatformInfo.isAndroid then return {} end

--==============================================================================
-- normal test execution starts below
--==============================================================================

	-- wf.core
local KSIdGenerator = require 'KSIdGenerator'
local KSPathUtils = require 'KSPathUtils'
local WFCatMockCatalog = require 'WFCatMockCatalog'
local WFFileUtils = require 'WFFileUtils'
local WFRxTestCase = require 'WFRxTestCase'

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

local PixelPathProviderScheduler = require "PixelPathProviderScheduler"
local PixelPathProviderRequestTypes = require "PixelPathProviderRequestTypes"

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

local PixelPathProviderRequestTypeNames = PixelPathProviderRequestTypes.names

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

local function makeSchedulerForTest( rxTest )

	local catalog = WFCatMockCatalog.createFakeWFCatalog( rxTest )

	local scheduler = PixelPathProviderScheduler( catalog )

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

	return scheduler, catalog

end

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

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

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

local _validOrigPath = KSPathUtils.child( testDataFolder1, "IMG_7763.jpg" )

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

local function addRecordToDocStore( rxTest, catalog, assetId, localAssetId,
										originalPath, w, h, subtype )

	local volumeGuid, relativePath

	if originalPath then

		volumeGuid = WFFileUtils.getVolumeGuidForPath( originalPath )
		
		if not volumeGuid then
			 volumeGuid = KSIdGenerator.uuidInLowercaseHex()
		end
		
		relativePath = WFFileUtils.removeVolumeFromPath( originalPath )

		if not relativePath then
			relativePath = originalPath
		end

	end

	local localOnly = originalPath and 
		{ 
			files = {
				original = {
					master = {
						relativePath = relativePath,
						volumeGuid = volumeGuid
					}
				}
			}
		} or nil

	rxTest:expectSingleValue(

		catalog:docStore():setDocValue {
			_id = assetId,
			_localId = localAssetId,
			_localOnly = localOnly,
			subtype = subtype,
			develop = {
				croppedHeight = h,
				croppedWidth = w,
				xmpCameraRaw = '<xmp />',
				userOrientation = 1,
			},
		},

		':ignore:' )

end

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

local function makePixStreamTuple( pixStreamId, assetId, 
										success, pixelPathOrError, maybeDigest, 
										maybeRenderSize, maybeRequestType )

	return { pixStreamId, 
				assetId,
				success, 
				success and "pixelPath" or pixelPathOrError, 
				maybeDigest and "digest" or nil, 
				maybeRenderSize,
				maybeRequestType }

end

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

local function makePixStreamErrTuple( ... )

	return { ... }

end

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

local function firstMatches( v )

	return function( wut )

		return wut == v

	end

end

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

local function stripFirstNAndPack( n )

	return function( ... )

		local ret = {}

		for i = n + 1, select( "#", ... ) do

			ret[ #ret + 1 ] = select( i, ... )

		end

		return ret

	end

end

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

local function testMessageStream( scheduler, wantedMsg )

	return scheduler._testData.testInfoStream
				:where( 
					function( msg ) 

						return msg == wantedMsg

					end )
				:map( stripFirstNAndPack( 1 ) )

end

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

local function rxTestHappyPath( rxTest )

	local scheduler, catalog = makeSchedulerForTest( rxTest )

	local SchedulerTestAPI = scheduler:_expose_test_API()

	SchedulerTestAPI.allowlistAllTasks( scheduler )

	local savedPixelPath

	local function savePixelPath( _, _, _, pixelPath )

		savedPixelPath = pixelPath

	end

	local watchHappyPathStream = rxTest:observe( 
									scheduler:pixelPathStream()
										:where( firstMatches( "happy path" ) )
										:tap( savePixelPath )
										:map( makePixStreamTuple ) )

	local assetId = KSIdGenerator.uuidInLowercaseHex()

	local localAssetId = 1

	addRecordToDocStore( rxTest, catalog, assetId, localAssetId, _validOrigPath, 1024, 1024, "image" )

	scheduler:addRequest( "happy path", localAssetId, 
							PixelPathProviderRequestTypeNames.grid_visible, 320 )

	watchHappyPathStream:expectData( { "happy path",
								localAssetId,
								true,
								"pixelPath",
								"digest",
								320,
								1024 } )

	rxTest:log( "making sure we got a happy path path" )

	rxTest:expectEqual( true, WFFileUtils.exists( savedPixelPath ) == "file" )

	-- now verify we just return from the cache without rendering

	rxTest:log( "making sure we did pixel cache check" )

	local watchPixelCacheCheck = 
				rxTest:observe( 
					testMessageStream( scheduler, "didPixelCacheCheck" )
					:take( 1 ) )

	-- request the same render
	scheduler:addRequest( "happy path", localAssetId, 
							PixelPathProviderRequestTypeNames.idle, 240 ) 

	watchPixelCacheCheck:expectData( { "happy path", localAssetId, 'have_rendition' } )

	watchHappyPathStream:expectData( { "happy path",
								localAssetId,
								true,
								"pixelPath",
								"digest",
								320,
								1024 } )

	rxTest:expectEqual( true, WFFileUtils.exists( savedPixelPath ) == "file" )

	WFFileUtils.delete( savedPixelPath )

	rxTest:expectEqual( false, WFFileUtils.exists( savedPixelPath ) )

end

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

local function rxTestMissingOriginal( rxTest )

	local scheduler, catalog = makeSchedulerForTest( rxTest )

	local watchStream = rxTest:observe( scheduler:pixelPathStream()
											:map( makePixStreamErrTuple ) )

	local assetId = KSIdGenerator.uuidInLowercaseHex()

	local localAssetId = 1

	addRecordToDocStore( rxTest, catalog, assetId, localAssetId, nil, 1024, 1024, "image" )

	scheduler:addRequest( "missing original", localAssetId, 
							PixelPathProviderRequestTypeNames.grid_visible, 320 )

	watchStream:expectData( { "missing original",
								localAssetId,
								false,
								"SendNoDownloadableRenderOrBinary" } )

end

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

local function rxTestBogusOriginal( rxTest )

	local scheduler, catalog = makeSchedulerForTest( rxTest )

	local watchStream = rxTest:observe( scheduler:pixelPathStream()
											:map( makePixStreamErrTuple ) )

	local assetId = KSIdGenerator.uuidInLowercaseHex()

	local localAssetId = 1

	local bogusPath = KSPathUtils.child( KSPathUtils.getStandardFilePath( 'carouselDocuments' ), 'bogus' )

	addRecordToDocStore( rxTest, catalog, assetId, localAssetId, bogusPath, 1024, 1024, "image" )

	scheduler:addRequest( "bogus original", localAssetId, 
							PixelPathProviderRequestTypeNames.grid_visible, 320 )

	watchStream:expectData( { "bogus original",
								localAssetId,
								false,
								"SendNoDownloadableRenderOrBinary" } )

end

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

local function bumpTimeLimit( f, n )

	return function( rxTest )

		rxTest:setTimeLimit( n )

		return f( rxTest )

	end

end

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

return WFRxTestCase.wrapSuite( 'PixelPathProviderSchedulerFullRunTest', {

	rxTestHappyPath = bumpTimeLimit( rxTestHappyPath, 8 ),
	
	rxTestMissingOriginal = rxTestMissingOriginal,

	rxTestBogusOriginal = bumpTimeLimit( rxTestBogusOriginal, 8 ),


} )
