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

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

----------------------------------------------------------------------------]]--
	-- RxLua
local Rx = require 'Rx'
local Disposable = Rx.Disposable

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

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

local runUntilDone = WFRxRunUntilDone

local kStreamIdSuffixMap = {
	original = '_original',
	proxy = '_proxy',
	xmp_develop = '_xmp_develop',
	xmp_sidecar = '_xmp_sidecar',
	rendition = '_rendition',
}

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

local function makePixStreamIdPixelPathStream( pixelProviderProcessor, pixStreamId, assetId )

	return pixelProviderProcessor
			:pixStreamIdPixelPathStream( pixStreamId )
			:where( 
				function( _, theAssetId )

					return theAssetId == assetId

				end )
			:tap( 
				function()

					pixelProviderProcessor:runUntilDone( 'removeRequest',
														pixStreamId, assetId )

				end )
			:take( 1 )

end

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

-- @mark WFCatExportPixelProviderTask class

--------------------------------------------------------------------------------
--[[!
	\brief WFCatExportPixelProviderTask caters to all pixel 
	related requirements of all Export Providers.
	
	Each WFCatExportPixelProviderTask is associated with a
	WFCatExportTask, so that it will be easier to
	cancel all the requests associated with a given
	session.
]]--

local WFCatExportPixelProviderTask = {

	Disposable,
	
	_taskId = false,
		-- ( string ) unique identifier for class. 
		
	_pixelProviderProcessorStream = false,
		-- ( Observable ) an observable which emits the pixel provider
		-- for the current catalog
	
}

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

function WFCatExportPixelProviderTask:__init( pixelProviderProcessorStream )
	self._taskId = string.format( 'Export_%s', KSIdGenerator.uuidInLowercaseHex() )
	self._pixelProviderProcessorStream = pixelProviderProcessorStream
end

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

function WFCatExportPixelProviderTask:dispose(  )
	
	--Cancel all the requests from this client
	--TOFIX: ashj: Will this abandon the requests
	-- sent to the old stream? Maybe if the stream
	-- is closed, then the requests also will be
	-- abandoned(?).
	if self._pixelProviderProcessorStream then
		self._pixelProviderProcessorStream
			:take( 1 )
			:tap( function( pixelProviderProcessor )
			
				for _, suffix in pairs( kStreamIdSuffixMap ) do

					local streamId = self._taskId .. suffix
					pixelProviderProcessor:runUntilDone(
											"abandonAllPixStreamRequests",
											streamId )
				end
			end)
			:call( runUntilDone )
	end
	
	-- pixelProviderProcessor stream is not owned by us.
	-- Lets not dispose it.
	self._pixelProviderProcessorStream = nil

	return self:Rx_Disposable_dispose()
end

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

function WFCatExportPixelProviderTask:getOriginal( assetId )
	
	return self._pixelProviderProcessorStream
			:take( 1 )
			:flatMapLatest(
				function( pixelProviderProcessor )

					if not pixelProviderProcessor then
						return Rx.Observable.throw( "request_closed" )
					end

					return Rx.Observable.create(
						function( observer )

							local pixStreamId = self._taskId .. kStreamIdSuffixMap[ 'original' ]
							local originalPathStream =
									makePixStreamIdPixelPathStream( 
										pixelProviderProcessor, pixStreamId, assetId )
						
							local subscription = 
									originalPathStream:subscribe( observer )

							pixelProviderProcessor:runUntilDone( 
													"requestOriginalForExport", 
														pixStreamId,
														assetId )

							return subscription
						
					end )
				
			end )
			:map( function( _, _, success, originalPath )

				return success, originalPath

			end )
end

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

function WFCatExportPixelProviderTask:getProxy( assetId )

	return self._pixelProviderProcessorStream
			:take( 1 )
			:flatMapLatest(
				function( pixelProviderProcessor )

					if not pixelProviderProcessor then
						return Rx.Observable.throw( "request_closed" )
					end

					return Rx.Observable.create(
						function( observer )

							local pixStreamId = self._taskId .. kStreamIdSuffixMap[ 'proxy' ]
							local originalPathStream =
									makePixStreamIdPixelPathStream( 
										pixelProviderProcessor, pixStreamId, assetId )

							local subscription = 
									originalPathStream:subscribe( observer )

							pixelProviderProcessor:runUntilDone( 
													"requestProxyForExport", 
														pixStreamId,
														assetId )

							return subscription

					end )

			end )
			:map( function( _, _, success, proxyPath )

				return success, proxyPath

			end )
end

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

function WFCatExportPixelProviderTask:getBiggestRenditionPath( assetId, canUseAnyRenditionSize )
	
	return self._pixelProviderProcessorStream
			:take( 1 )
			:flatMapLatest(
				function( pixelProviderProcessor )

					if not pixelProviderProcessor then
						return Rx.Observable.throw( "request_closed" )
					end

					return Rx.Observable.create(
						function( observer )

							local pixStreamId = self._taskId .. kStreamIdSuffixMap[ 'rendition' ]

							local renditionPathStream =
									makePixStreamIdPixelPathStream( 
										pixelProviderProcessor, pixStreamId, assetId )
						
							local subscription = 
									renditionPathStream:subscribe( observer )

							local pixelProviderAPI = 
								not canUseAnyRenditionSize and
									"requestFullSizeRenditionForExport" or
									"requestBiggestPossibleRenditionForExport"

							pixelProviderProcessor:runUntilDone( 
													pixelProviderAPI,
														pixStreamId,
														assetId )

							return subscription
						
					end )
				
			end )
			:map( function( _, _, success, renditionPath )

				return success, renditionPath

			end )

end

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

function WFCatExportPixelProviderTask:getXmpDevelop( assetId )
	
	return self._pixelProviderProcessorStream
			:take( 1 )
			:flatMapLatest(
				function( pixelProviderProcessor )

					if not pixelProviderProcessor then
						return Rx.Observable.throw( "request_closed" )
					end
					
					return Rx.Observable.create(
						function( observer )

							local pixStreamId = self._taskId .. kStreamIdSuffixMap[ 'xmp_develop' ]
							local xmpDevelopPathStream =
									makePixStreamIdPixelPathStream( 
										pixelProviderProcessor, pixStreamId, assetId )

							local subscription = 
									xmpDevelopPathStream:subscribe( observer )

							pixelProviderProcessor:runUntilDone( 
													"requestXmpDevelopForExport", 
														pixStreamId,
														assetId )

							return subscription

					end )

			end )
			:map( function( _, _, success, xmpDevelopPath )

				return success, xmpDevelopPath

			end )

end

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

function WFCatExportPixelProviderTask:getXmpSidecar( assetId )

	return self._pixelProviderProcessorStream
			:take( 1 )
			:flatMapLatest(
				function( pixelProviderProcessor )

					if not pixelProviderProcessor then
						return Rx.Observable.throw( "request_closed" )
					end

					return Rx.Observable.create(
						function( observer )

							local pixStreamId = self._taskId .. kStreamIdSuffixMap[ 'xmp_sidecar' ]
							local xmpPathStream =
									makePixStreamIdPixelPathStream(
										pixelProviderProcessor, pixStreamId, assetId )

							local subscription =
									xmpPathStream:subscribe( observer )

							pixelProviderProcessor:runUntilDone(
													"requestXmpSidecarForExport",
														pixStreamId,
														assetId )

							return subscription

					end )

			end )
			:map( function( _, _, success, xmpSidecarPath )

				return success, xmpSidecarPath

			end )

end

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

return Rx.Class 'WFCatExportPixelProviderTask'( WFCatExportPixelProviderTask )
