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

PixelProviderFetchXmpDevelopTask.lua

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

ADOBE CONFIDENTIAL
------------------
Copyright 2016 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
local Foreign
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.

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

local Rx = require 'Rx'
local Observable = Rx.Observable

local PixelPathProviderStateMachine = require 'PixelPathProviderStateMachine'
local PixelPathProviderSchedulerPrivateMethods =
		require "PixelPathProviderSchedulerPrivateMethods"
local WFAsyncFileUtils = require 'WFAsyncFileUtils'

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

local logger = require 'WFLogger'( 'PixelProviderFetchXmpDevelopTask' )

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

local LocalBinaryPathCheckStates = PixelPathProviderStateMachine.LocalBinaryPathCheckStates

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

local _needsExternalSettingsStates = {
		LocalBinaryPathCheckStates.FetchLocalXmpDevelopForRender,
		}

--------------------------------------------------------------------------------
-- setupTask
--------------------------------------------------------------------------------

local function setupTask( _, fileSpec, maxConcurrentFetches )
	
	return { 
			fileSpec = fileSpec,
			 maxConcurrentFetches = maxConcurrentFetches,
			 pendingFetchSubscriptions = {}
		}

end
		
--------------------------------------------------------------------------------
-- processRequests
--------------------------------------------------------------------------------

local function maybeGetUnusedPendingFetchNumber( taskState )

	local pendingFetchNumber

	for i = 1, taskState.maxConcurrentFetches do

		pendingFetchNumber = 
			pendingFetchNumber or
			( not taskState.pendingFetchSubscriptions[ i ] and i ) or
			nil

	end

	return pendingFetchNumber

end
--------------------------------------------------------------------------------

local function processRequests( scheduler, taskState, baseRenderInfoCache,
								currRenderSettingsCache )
	
	local pendingFetchNumber
	
	repeat
	
		pendingFetchNumber = pendingFetchNumber or maybeGetUnusedPendingFetchNumber( taskState )
		
		if not pendingFetchNumber then
			break
		end
		
		local request =
			{ PixelPathProviderSchedulerPrivateMethods.getNextRequestWithState( 
				scheduler,  unpack( _needsExternalSettingsStates ) ) }

		local pixStreamId, localAssetId = unpack( request )

		if not pixStreamId then
			-- nothing needs fetching
			break
		end
		
		scheduler:_applyTransitionToRequest( request, 'start_read_dev_xmp' )
		
		local baseRenderInfo = baseRenderInfoCache:peekCacheItem( localAssetId ) or {}
		
		local localPath = baseRenderInfo.xmpDevelopPath
		
		if not baseRenderInfo then
		
			scheduler:_applyTransitionToRequest( request, 'need_docstore_info' )
		
		elseif not localPath then
		
			scheduler:_applyTransitionToRequest( request, 'need_download_dev_xmp' )
			
		else
			-- we have localPath
			local digest = baseRenderInfo.digest
			local revId = baseRenderInfo.revId
			local userOrientation = baseRenderInfo.userOrientation
			
			local currPendingFetchNumber = pendingFetchNumber
			pendingFetchNumber = nil
				
			taskState.pendingFetchSubscriptions[ currPendingFetchNumber ] = 
			
				WFAsyncFileUtils.readFile( localPath )
					:catch( function( errorMessage ) 
						logger:errorf( "Error reading from %s for %s(%s): %s", 	
							localPath, pixStreamId, localAssetId, errorMessage )
							
						return Observable.just( nil )
					end )
					:subscribe( function( externalSettings )
						
						taskState.pendingFetchSubscriptions[ currPendingFetchNumber ] = nil
					
						if externalSettings then
						
							currRenderSettingsCache:pushCacheItem( 
														localAssetId, 
														{ digest, 
															revId,
															tostring( externalSettings ),
															userOrientation } ) 
							
							externalSettings:close()
							
							-- this is a thread callback, so must use _maybeSetNextState	
							scheduler:_maybeSetNextState( pixStreamId, localAssetId, 'finished_read_dev_xmp' )
							
						else
							
							scheduler:_maybeSetNextState( pixStreamId, localAssetId, 'need_download_dev_xmp' )
							
						end
					end )
		end
		
	until false
	
end

--------------------------------------------------------------------------------
-- cleanup
--------------------------------------------------------------------------------

local function cleanup()

end

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

return {

	setupTask = setupTask,

	processRequests = processRequests,

	cleanup = cleanup,

}


