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

XmpDevelopStateMachine.lua

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

ADOBE CONFIDENTIAL
------------------
Copyright 2022 Adobe
All Rights Reserved.

NOTICE: All information contained herein is, and remains
the property of Adobe and its suppliers, if any. The intellectual
and technical concepts contained herein are proprietary to Adobe
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.
------------------------------------------------------------------------------]]

	-- wf.core
local WFFiniteStateMachine = require 'WFFiniteStateMachine'

--==============================================================================
-- This file encapsulates all of the states we can go through when checking
-- for local external xmp data
--==============================================================================

local function addDocStoreInfoStates( fsm, docstoreInfoStateGroupName )

	return WFFiniteStateMachine.addGroupedStates(
			fsm, docstoreInfoStateGroupName,
			{
				'NeedXmpDevelopInfo',
				'NeedXmpDevelopInfoFromDocstore',
				'FetchingXmpDevelopInfo',
				'NeedCheckIfXmpDevelopInlineOrExternal',
				'UseDefaultRenderSettingsForMissingXmpDevelopRender',
			} )

end

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

local function addLocalBinaryPathCheckStates( fsm, localBinaryPathCheckStateGroupName )

	return WFFiniteStateMachine.addGroupedStates(
			fsm, localBinaryPathCheckStateGroupName,
			{
				'NeedCheckIfExternalXmpDevelopIsLocal',
				'CheckingIfExternalXmpDevelopIsLocal',
				'RenditionStrategyNeedCheckIfExternalXmpDevelopIsLocal',
				'RenditionStrategyCheckingIfExternalXmpDevelopIsLocal',
				'NeedCheckIfExternalDevelopAuxFilesAreLocal',
				'CheckingIfExternalDevelopAuxFilesAreLocal',
				'RenditionStrategyNeedCheckIfExternalDevelopAuxFilesAreLocal',
				'RenditionStrategyCheckingIfExternalDevelopAuxFilesAreLocal',
				'RenderFetchLocalExternalXmpDevelop',
				'RenderFetchingLocalXmpDevelop',
			} )

end

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

local function addDownloadStates( fsm, downloadStateGroupName )

	return WFFiniteStateMachine.addGroupedStates(
			fsm, downloadStateGroupName,
			{
				'NeedXmpDevelopDownload',
				'DownloadingXmpDevelop',
				'RenderNeedXmpDevelopDownload',
				'RenderDownloadingXmpDevelop',
				'NeedExternalDevelopAuxFilesDownload',
				'DownloadingExternalAuxFiles',
				'RenderNeedExternalDevelopAuxFilesDownload',
				'RenderDownloadingExternalAuxFiles',
			} )

end

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

local function addSaveDownloadStates( fsm, saveDownloadStateGroupName )

	return WFFiniteStateMachine.addGroupedStates(
			fsm, saveDownloadStateGroupName,
			{
				'NeedToSaveXmpDevelop',
				'SavingXmpDevelop',
				'RenderNeedToSaveXmpDevelop',
				'RenderSavingXmpDevelop',
			} )

end

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

local function addSendDataStates( fsm, sendDataStateGroupName )

	return WFFiniteStateMachine.addGroupedStates(
			fsm, sendDataStateGroupName,
			{
				'SendNoDownloadableXmpDevelop',
				'HaveLocalXmpDevelopPath',
				'HaveEmbeddedXmpDevelopNotExternal',
				'SendMissingExpectedXmpDevelopUrl',
				'SendMissingExpectedXmpDevelopUrlForRender',
				'SendBadExternalDevelopAuxFileSequence',
			} )

end

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

local function addEndStates( fsm, endStateGroupName )

	return WFFiniteStateMachine.addGroupedStates(
			fsm, endStateGroupName,
			{
				'NoDownloadableXmpDevelop',
				'FinishedSendingXmpDevelopPath',
				'BadExternalDevelopAuxFileSequence',
				'MissingExpectedXmpDevelopUrl',
				'MissingExpectedXmpDevelopUrlForRender',
			} )

end

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

local function addDocStoreInfoStateTransitions( fsm, PixelPathProviderStateMachine )

	local DocstoreInfoStates = PixelPathProviderStateMachine.DocstoreInfoStates

	local LocalBinaryPathCheckStates = PixelPathProviderStateMachine.LocalBinaryPathCheckStates

	local PixelCacheCheckStates = PixelPathProviderStateMachine.PixelCacheCheckStates

	local SendDataStates = PixelPathProviderStateMachine.SendDataStates

	fsm = WFFiniteStateMachine.addTransitions(
			fsm,
			DocstoreInfoStates.NeedXmpDevelopInfo,
			{
				{ 'must_fetch', DocstoreInfoStates.NeedXmpDevelopInfoFromDocstore },
				{ 'already_present', DocstoreInfoStates.NeedCheckIfXmpDevelopInlineOrExternal },
				{ 'bad_asset_id', SendDataStates.SendPermanentBadAssetIdError }
		  	} )

	fsm = WFFiniteStateMachine.addTransitions(
			fsm,
			DocstoreInfoStates.NeedXmpDevelopInfoFromDocstore,
			{
				{ 'start_docstore_read', DocstoreInfoStates.FetchingXmpDevelopInfo },
				{ 'received_docstore_read', DocstoreInfoStates.NeedCheckIfXmpDevelopInlineOrExternal }
			} )

	fsm = WFFiniteStateMachine.addTransitions(
			fsm,
			DocstoreInfoStates.FetchingXmpDevelopInfo,
			{
				{ 'received_docstore_read', DocstoreInfoStates.NeedCheckIfXmpDevelopInlineOrExternal },
				{ 'bad_asset_id', SendDataStates.SendPermanentBadAssetIdError }
			} )

	fsm = WFFiniteStateMachine.addTransitions(
			fsm,
			DocstoreInfoStates.NeedCheckIfXmpDevelopInlineOrExternal,
			{
				{ 'xmp_develop_and_aux_files_are_external',  LocalBinaryPathCheckStates.NeedCheckIfExternalXmpDevelopIsLocal },
				{ 'xmp_develop_is_external',  LocalBinaryPathCheckStates.NeedCheckIfExternalXmpDevelopIsLocal },
				{ 'have_xmp_develop',  SendDataStates.HaveEmbeddedXmpDevelopNotExternal }
			} )

	fsm = WFFiniteStateMachine.addTransitions(
			fsm,
			DocstoreInfoStates.UseDefaultRenderSettingsForMissingXmpDevelopRender,
			{
				{ 'use_default_settings', PixelCacheCheckStates.NeedCheckForPixelPathInCache }
			} )

	return fsm

end

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

local function addLocalBinaryPathCheckStateTransitions( fsm, PixelPathProviderStateMachine )

	local DocstoreInfoStates = PixelPathProviderStateMachine.DocstoreInfoStates

	local LocalBinaryPathCheckStates = PixelPathProviderStateMachine.LocalBinaryPathCheckStates

	local DownloadStates = PixelPathProviderStateMachine.DownloadStates

	local PixelCacheCheckStates = PixelPathProviderStateMachine.PixelCacheCheckStates

	local SaveDownloadStates = PixelPathProviderStateMachine.SaveDownloadStates

	local SendDataStates = PixelPathProviderStateMachine.SendDataStates

	-- check for external xmp develop
	fsm = WFFiniteStateMachine.addTransitions(
			fsm,
			LocalBinaryPathCheckStates.NeedCheckIfExternalXmpDevelopIsLocal,
			{
				{ 'start_local_develop_files_check', LocalBinaryPathCheckStates.CheckingIfExternalXmpDevelopIsLocal },
				{ 'join_existing_xmp_develop_download', DownloadStates.NeedXmpDevelopDownload },
				{ 'join_existing_xmp_develop_save', SaveDownloadStates.NeedToSaveXmpDevelop },
				{ 'missing_expected_external_develop_file_info', SendDataStates.SendPermanentError },
				{ 'new_docstore_render_info', DocstoreInfoStates.NeedXmpDevelopInfoFromDocstore },
				{ 'missing_external_develop_file_docstore_info', DocstoreInfoStates.NeedXmpDevelopInfoFromDocstore },
			} )

	fsm = WFFiniteStateMachine.addTransitions(
			fsm,
			LocalBinaryPathCheckStates.CheckingIfExternalXmpDevelopIsLocal,
			{
				{ 'has_all_local_develop_files', SendDataStates.HaveLocalXmpDevelopPath },
				{ 'need_download_external_develop_xmp', DownloadStates.NeedXmpDevelopDownload },
				{ 'missing_needed_develop_xmp_link', SendDataStates.SendMissingExpectedXmpDevelopUrl },
				{ 'need_download_one_or_more_external_aux_files', DownloadStates.NeedExternalDevelopAuxFilesDownload },
				{ 'need_new_xmp_develop_info_from_docstore', DocstoreInfoStates.NeedXmpDevelopInfoFromDocstore },
				{ 'redo_xmp_develop_check', DocstoreInfoStates.NeedXmpDevelopInfoFromDocstore },
				{ 'unexpected_external_develop_file_check_exception', SendDataStates.SendPermanentError },
			} )

	-- checking for external masks
	fsm = WFFiniteStateMachine.addTransitions(
			fsm,
			LocalBinaryPathCheckStates.NeedCheckIfExternalDevelopAuxFilesAreLocal,
			{
				{ 'skip_aux_file_check', SendDataStates.HaveLocalXmpDevelopPath },
				{ 'start_local_develop_files_check', LocalBinaryPathCheckStates.CheckingIfExternalDevelopAuxFilesAreLocal },
				{ 'join_existing_external_aux_file_download', DownloadStates.NeedExternalDevelopAuxFilesDownload },
				{ 'all_external_develop_xmp_are_downloaded', SendDataStates.HaveLocalXmpDevelopPath },
				{ 'missing_expected_external_develop_file_info', SendDataStates.SendPermanentError },
				{ 'new_docstore_render_info', DocstoreInfoStates.NeedXmpDevelopInfoFromDocstore },
				{ 'missing_external_develop_file_docstore_info', DocstoreInfoStates.NeedXmpDevelopInfoFromDocstore },
			} )

	fsm = WFFiniteStateMachine.addTransitions(
			fsm,
			LocalBinaryPathCheckStates.CheckingIfExternalDevelopAuxFilesAreLocal,
			{
				{ 'has_all_local_develop_files', SendDataStates.HaveLocalXmpDevelopPath },
				-- we do not expect the external develop xmp to be missing if checking for masks
				{ 'need_download_external_develop_xmp', SendDataStates.SendBadExternalDevelopAuxFileSequence },
				{ 'need_download_one_or_more_external_aux_files', DownloadStates.NeedExternalDevelopAuxFilesDownload },
				{ 'need_new_xmp_develop_info_from_docstore', DocstoreInfoStates.NeedXmpDevelopInfoFromDocstore },
				{ 'redo_xmp_develop_check', DocstoreInfoStates.NeedXmpDevelopInfoFromDocstore },
				{ 'unexpected_external_develop_file_check_exception', SendDataStates.SendPermanentError },
			} )

	-- check for xmp_develop to use for rendering
	fsm = WFFiniteStateMachine.addTransitions(
			fsm,
			LocalBinaryPathCheckStates.RenditionStrategyNeedCheckIfExternalXmpDevelopIsLocal,
			{
				{ 'start_local_develop_files_check', LocalBinaryPathCheckStates.RenditionStrategyCheckingIfExternalXmpDevelopIsLocal },
				{ 'join_existing_xmp_develop_download', DownloadStates.RenderNeedXmpDevelopDownload },
				{ 'join_existing_xmp_develop_save', SaveDownloadStates.RenderNeedToSaveXmpDevelop },
				{ 'missing_expected_external_develop_file_info', SendDataStates.SendPermanentError },
				{ 'new_docstore_render_info', PixelCacheCheckStates.ChooseRenditionStrategy },
				{ 'missing_external_develop_file_docstore_info', PixelCacheCheckStates.ChooseRenditionStrategy },
			} )

	fsm = WFFiniteStateMachine.addTransitions(
			fsm,
			LocalBinaryPathCheckStates.RenditionStrategyCheckingIfExternalXmpDevelopIsLocal,
			{
				{ 'has_all_local_develop_files', LocalBinaryPathCheckStates.RenderFetchLocalExternalXmpDevelop },
				{ 'need_download_external_develop_xmp', DownloadStates.RenderNeedXmpDevelopDownload },
				{ 'missing_needed_develop_xmp_link', SendDataStates.SendMissingExpectedXmpDevelopUrlForRender },
				{ 'need_download_one_or_more_external_aux_files', DownloadStates.RenderNeedExternalDevelopAuxFilesDownload },
				{ 'need_new_xmp_develop_info_from_docstore', PixelCacheCheckStates.ChooseRenditionStrategy },
				{ 'redo_xmp_develop_check', PixelCacheCheckStates.ChooseRenditionStrategy },
				{ 'unexpected_external_develop_file_check_exception', SendDataStates.SendPermanentError },
			} )

	-- checking for external masks for render
	fsm = WFFiniteStateMachine.addTransitions(
			fsm,
			LocalBinaryPathCheckStates.RenditionStrategyNeedCheckIfExternalDevelopAuxFilesAreLocal,
			{
				{ 'skip_aux_file_check', LocalBinaryPathCheckStates.RenderFetchLocalExternalXmpDevelop },
				{ 'start_local_develop_files_check', LocalBinaryPathCheckStates.RenditionStrategyCheckingIfExternalDevelopAuxFilesAreLocal },
				{ 'join_existing_external_aux_file_download', DownloadStates.RenderNeedExternalDevelopAuxFilesDownload },
				{ 'all_external_develop_xmp_are_downloaded', LocalBinaryPathCheckStates.RenderFetchLocalExternalXmpDevelop },
				{ 'missing_expected_external_develop_file_info', SendDataStates.SendPermanentError },
				{ 'new_docstore_render_info', PixelCacheCheckStates.ChooseRenditionStrategy },
				{ 'missing_external_develop_file_docstore_info', PixelCacheCheckStates.ChooseRenditionStrategy },
			} )

	fsm = WFFiniteStateMachine.addTransitions(
			fsm,
			LocalBinaryPathCheckStates.RenditionStrategyCheckingIfExternalDevelopAuxFilesAreLocal,
			{
				{ 'has_all_local_develop_files', LocalBinaryPathCheckStates.RenderFetchLocalExternalXmpDevelop },
				-- we do not expect the external develop xmp to be missing if checking for masks
				{ 'need_download_external_develop_xmp', SendDataStates.SendBadExternalDevelopAuxFileSequence },
				{ 'need_download_one_or_more_external_aux_files', DownloadStates.RenderNeedExternalDevelopAuxFilesDownload },
				{ 'need_new_xmp_develop_info_from_docstore', PixelCacheCheckStates.ChooseRenditionStrategy },
				{ 'redo_xmp_develop_check', PixelCacheCheckStates.ChooseRenditionStrategy },
				{ 'unexpected_external_develop_file_check_exception', SendDataStates.SendPermanentError },
			} )
	
	-- reading external xmp into memory so we can render
	fsm = WFFiniteStateMachine.addTransitions(
			fsm,
			LocalBinaryPathCheckStates.RenderFetchLocalExternalXmpDevelop,
			{ 
				{ 'start_reading_external_xmp_develop_path', LocalBinaryPathCheckStates.RenderFetchingLocalXmpDevelop },
				{ 'missing_expected_external_xmp_develop_path', SendDataStates.SendPermanentError },
			} )
	
	fsm = WFFiniteStateMachine.addTransitions(
			fsm,
			LocalBinaryPathCheckStates.RenderFetchingLocalXmpDevelop,
			{ 
				{ 'finished_reading_external_xmp_develop_path', PixelCacheCheckStates.NeedCheckForPixelPathInCache },
				{ 'failed_reading_external_xmp_develop_path', SendDataStates.SendPermanentError } 
			} )

	return fsm

end

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

local function addDownloadStateTransitions( fsm, PixelPathProviderStateMachine )

	local DocstoreInfoStates = PixelPathProviderStateMachine.DocstoreInfoStates

	local LocalBinaryPathCheckStates = PixelPathProviderStateMachine.LocalBinaryPathCheckStates

	local DownloadStates = PixelPathProviderStateMachine.DownloadStates

	local SaveDownloadStates = PixelPathProviderStateMachine.SaveDownloadStates

	local SendDataStates = PixelPathProviderStateMachine.SendDataStates

	-- download xmp develop

	fsm = WFFiniteStateMachine.addTransitions(
			fsm,
			DownloadStates.NeedXmpDevelopDownload, 
			{
				{ 'start_download', DownloadStates.DownloadingXmpDevelop },
				{ 'missing_download_info', SendDataStates.SendMissingExpectedXmpDevelopUrl },
				{ 'start_save_download', SaveDownloadStates.SavingXmpDevelop },
				{ 'cannot_download', SendDataStates.SendPermanentDownloadError },
				{ 'no_internet', SendDataStates.SendPermanentDownloadError },
				{ 'volume_cannot_save', SendDataStates.SendPermanentDownloadError },
				{ 'have_pending_save_for_blob', SaveDownloadStates.NeedToSaveXmpDevelop },
				{ 'saved_valid_download', LocalBinaryPathCheckStates.NeedCheckIfExternalDevelopAuxFilesAreLocal }
			} )

	fsm = WFFiniteStateMachine.addTransitions(
			fsm,
			DownloadStates.DownloadingXmpDevelop, 
			{
				{ 'retry_download', SendDataStates.SendPermanentDownloadError },
				{ 'cannot_retry_download', SendDataStates.SendPermanentDownloadError },
				{ 'missing_download_info', DocstoreInfoStates.NeedXmpDevelopInfo },
				{ 'received_download', SaveDownloadStates.NeedToSaveXmpDevelop },
				{ 'reschedule_download', DownloadStates.NeedXmpDevelopDownload },
			} )
			
	-- download xmp develop as part of rendition render

	fsm = WFFiniteStateMachine.addTransitions(
			fsm,
			DownloadStates.RenderNeedXmpDevelopDownload,
			{
				{ 'start_download', DownloadStates.RenderDownloadingXmpDevelop },
				{ 'missing_download_info', SendDataStates.SendMissingExpectedXmpDevelopUrlForRender },
				{ 'start_save_download', SaveDownloadStates.RenderSavingXmpDevelop },
				{ 'cannot_download', SendDataStates.SendPermanentDownloadError },
				{ 'no_internet', SendDataStates.SendPermanentDownloadError },
				{ 'volume_cannot_save', SendDataStates.SendPermanentDownloadError },
				{ 'have_pending_save_for_blob', SaveDownloadStates.RenderNeedToSaveXmpDevelop },
				{ 'saved_valid_download', LocalBinaryPathCheckStates.RenditionStrategyNeedCheckIfExternalDevelopAuxFilesAreLocal },
			} )

	fsm = WFFiniteStateMachine.addTransitions(
			fsm,
			DownloadStates.RenderDownloadingXmpDevelop,
			{
				{ 'retry_download', SendDataStates.SendPermanentDownloadError },
				{ 'cannot_retry_download', SendDataStates.SendPermanentDownloadError },
				{ 'missing_download_info', DocstoreInfoStates.NeedAssetInfoForRender },
				{ 'received_download', SaveDownloadStates.RenderNeedToSaveXmpDevelop },
				{ 'reschedule_download', DownloadStates.RenderNeedXmpDevelopDownload },
			} )

	local PixelCacheCheckStates = PixelPathProviderStateMachine.PixelCacheCheckStates

	-- download external masks 

	fsm = WFFiniteStateMachine.addTransitions(
			fsm,
			DownloadStates.NeedExternalDevelopAuxFilesDownload,
			{
				{ 'missing_need_xmp_develop_download_cache_data', SendDataStates.SendPermanentError },
				{ 'start_xmp_develop_download', DownloadStates.DownloadingExternalAuxFiles },
				{ 'all_external_develop_xmp_are_downloaded', SendDataStates.HaveLocalXmpDevelopPath },
			} )

	fsm = WFFiniteStateMachine.addTransitions(
			fsm,
			DownloadStates.DownloadingExternalAuxFiles, 
			{
				{ 'external_develop_xmp_data_changed', DocstoreInfoStates.NeedXmpDevelopInfo },
				{ 'all_external_develop_xmp_are_downloaded', SendDataStates.HaveLocalXmpDevelopPath },
				{ 'failed_to_download_one_or_more_external_develop_uri', SendDataStates.SendNoDownloadableXmpDevelop },
				{ 'unexpected_external_develop_file_check_exception', SendDataStates.SendPermanentError },
			} )
			
	-- download external masks as part of rendition render

	fsm = WFFiniteStateMachine.addTransitions(
			fsm,
			DownloadStates.RenderNeedExternalDevelopAuxFilesDownload,
			{
				{ 'missing_need_xmp_develop_download_cache_data', SendDataStates.SendPermanentError },
				{ 'start_xmp_develop_download', DownloadStates.RenderDownloadingExternalAuxFiles },
				{ 'all_external_develop_xmp_are_downloaded', LocalBinaryPathCheckStates.RenderFetchLocalExternalXmpDevelop },
			} )

	fsm = WFFiniteStateMachine.addTransitions(
			fsm,
			DownloadStates.RenderDownloadingExternalAuxFiles,
			{
				{ 'external_develop_xmp_data_changed', PixelCacheCheckStates.ChooseRenditionStrategy },
				{ 'all_external_develop_xmp_are_downloaded', LocalBinaryPathCheckStates.RenderFetchLocalExternalXmpDevelop },
				{ 'failed_to_download_one_or_more_external_develop_uri', DocstoreInfoStates.UseDefaultRenderSettingsForMissingXmpDevelopRender },
				{ 'unexpected_external_develop_file_check_exception', SendDataStates.SendPermanentError },
			} )

	return fsm

end

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

local function addSaveDownloadStateTransitions( 
				fsm, PixelPathProviderStateMachine )

	local DocstoreInfoStates = PixelPathProviderStateMachine.DocstoreInfoStates

	local SaveDownloadStates = PixelPathProviderStateMachine.SaveDownloadStates

	local LocalBinaryPathCheckStates = PixelPathProviderStateMachine.LocalBinaryPathCheckStates

	local SendDataStates = PixelPathProviderStateMachine.SendDataStates
	
	-- just save xmp_develop

	fsm = WFFiniteStateMachine.addTransitions(
			fsm,
			SaveDownloadStates.NeedToSaveXmpDevelop, 
			{
				{ 'start_save_download', SaveDownloadStates.SavingXmpDevelop },
				{ 'saved_valid_download', LocalBinaryPathCheckStates.NeedCheckIfExternalDevelopAuxFilesAreLocal },
				{ 'no_binary_blob', SendDataStates.SendPermanentError },
			} )

	fsm = WFFiniteStateMachine.addTransitions(
			fsm,
			SaveDownloadStates.SavingXmpDevelop, 
			{
				-- treat temp_xmp_develop_sha256_mismatch like new_docstore_render_info
				{ 'temp_xmp_develop_sha256_mismatch', DocstoreInfoStates.NeedXmpDevelopInfo },
				{ 'save_downloaded_blob_failed', SendDataStates.SendPermanentError },
				{ 'fatal_xmp_develop_sha256_mismatch', SendDataStates.SendPermanentError },
				{ 'saved_valid_download', LocalBinaryPathCheckStates.NeedCheckIfExternalDevelopAuxFilesAreLocal }
			} )
	
	-- save xmp_develop then render
	fsm = WFFiniteStateMachine.addTransitions(
			fsm,
			SaveDownloadStates.RenderNeedToSaveXmpDevelop,
			{
				{ 'start_save_download', SaveDownloadStates.RenderSavingXmpDevelop },
				{ 'saved_valid_download', LocalBinaryPathCheckStates.RenditionStrategyNeedCheckIfExternalDevelopAuxFilesAreLocal },
				{ 'no_binary_blob', SendDataStates.SendPermanentError },
			} )

	fsm = WFFiniteStateMachine.addTransitions(
			fsm,
			SaveDownloadStates.RenderSavingXmpDevelop, 
			{
				-- treat temp_xmp_develop_sha256_mismatch like new_docstore_render_info
				{ 'temp_xmp_develop_sha256_mismatch', LocalBinaryPathCheckStates.RenditionStrategyNeedCheckIfExternalXmpDevelopIsLocal },
				{ 'save_downloaded_blob_failed', SendDataStates.SendPermanentError },
				{ 'fatal_xmp_develop_sha256_mismatch', SendDataStates.SendPermanentError },
				{ 'saved_valid_download', LocalBinaryPathCheckStates.RenditionStrategyNeedCheckIfExternalDevelopAuxFilesAreLocal },
			} )

	return fsm

end

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

local function addSendDataStateTransitions( 
				fsm, PixelPathProviderStateMachine )

	local DocstoreInfoStates = PixelPathProviderStateMachine.DocstoreInfoStates

	local SendDataStates = PixelPathProviderStateMachine.SendDataStates

	local LocalBinaryPathCheckStates = PixelPathProviderStateMachine.LocalBinaryPathCheckStates

	local EndStates = PixelPathProviderStateMachine.EndStates

	fsm = WFFiniteStateMachine.addTransitions(
			fsm, 
			SendDataStates.HaveLocalXmpDevelopPath,
			{
				{ 'missing_expected_path_computed_in_previous_step', SendDataStates.SendPermanentError },
				{ 'sent', EndStates.FinishedSendingXmpDevelopPath } 
			} )

	fsm = WFFiniteStateMachine.addTransitions(
			fsm, 
			SendDataStates.HaveEmbeddedXmpDevelopNotExternal,
			{
				{ 'sent', EndStates.FinishedSendingXmpDevelopPath } 
			} )

	fsm = WFFiniteStateMachine.addTransitions(
			fsm, 
			SendDataStates.SendBadExternalDevelopAuxFileSequence,
			{
				{ 'sent', EndStates.BadExternalDevelopAuxFileSequence } 
			} )
							  
	fsm = WFFiniteStateMachine.addTransitions(
			fsm, 
			SendDataStates.SendMissingExpectedXmpDevelopUrl,
			{ 
				{ 'sent', EndStates.MissingExpectedXmpDevelopUrl },
				{ 'new_docstore_render_info', DocstoreInfoStates.NeedXmpDevelopInfo } 
			} )
							  
	fsm = WFFiniteStateMachine.addTransitions(
			fsm, 
			SendDataStates.SendMissingExpectedXmpDevelopUrlForRender,
			{ 
				{ 'sent', EndStates.MissingExpectedXmpDevelopUrlForRender },
				{ 'new_docstore_render_info', LocalBinaryPathCheckStates.RenditionStrategyNeedCheckIfExternalXmpDevelopIsLocal } 
			} )
							  
	fsm = WFFiniteStateMachine.addTransitions(
			fsm, 
			SendDataStates.SendNoDownloadableXmpDevelop,
			{ 
				{ 'sent', EndStates.NoDownloadableXmpDevelop },
				{ 'new_docstore_render_info', DocstoreInfoStates.NeedXmpDevelopInfo } 
			} )
	
	return fsm

end

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

local function addEndStateTransitions( fsm, PixelPathProviderStateMachine )

	local DocstoreInfoStates = PixelPathProviderStateMachine.DocstoreInfoStates

	local LocalBinaryPathCheckStates = PixelPathProviderStateMachine.LocalBinaryPathCheckStates

	local EndStates = PixelPathProviderStateMachine.EndStates

	fsm = WFFiniteStateMachine.addTransitions(
			fsm, 
			EndStates.NoDownloadableXmpDevelop,
			{ 
				{ 'new_docstore_render_info', DocstoreInfoStates.NeedXmpDevelopInfo },
			} )
			
	fsm = WFFiniteStateMachine.addTransitions(
			fsm, 
			EndStates.MissingExpectedXmpDevelopUrl,
			{ 
				{ 'new_docstore_render_info', DocstoreInfoStates.NeedXmpDevelopInfo } 
			} )
	
	fsm = WFFiniteStateMachine.addTransitions(
			fsm, 
			EndStates.MissingExpectedXmpDevelopUrlForRender,
			{ 
				{ 'new_docstore_render_info', LocalBinaryPathCheckStates.RenditionStrategyNeedCheckIfExternalXmpDevelopIsLocal } 
			} )
	
	return fsm

end

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

local function addTransitions( fsm, PixelPathProviderStateMachine )

	fsm = addDocStoreInfoStateTransitions(
			fsm, PixelPathProviderStateMachine )

	fsm = addLocalBinaryPathCheckStateTransitions(
			fsm, PixelPathProviderStateMachine )

	fsm = addDownloadStateTransitions( fsm, PixelPathProviderStateMachine )

	fsm = addSaveDownloadStateTransitions( fsm, PixelPathProviderStateMachine )
	
	fsm = addSendDataStateTransitions( fsm, PixelPathProviderStateMachine )
	
	fsm = addEndStateTransitions( fsm, PixelPathProviderStateMachine )

	return fsm

end

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

local function getEnsureLocalDevelopSettingsStartFinishStates()

	local PixelPathProviderStateMachine = 
			require "PixelPathProviderStateMachine"

	local DocstoreInfoStates = PixelPathProviderStateMachine.DocstoreInfoStates

	local startStates = {

		[ DocstoreInfoStates.NeedXmpDevelopInfo ] =
			DocstoreInfoStates.NeedXmpDevelopInfo,

	}

	local EndStates = PixelPathProviderStateMachine.EndStates

	local finishStates = {

		[ EndStates.FinishedSendingXmpDevelopPath ] =
			EndStates.FinishedSendingXmpDevelopPath,

		[ EndStates.NoDownloadableXmpDevelop ] =
			EndStates.NoDownloadableXmpDevelop,

		[ EndStates.PermanentBadAssetIdError ] =
			EndStates.PermanentBadAssetIdError,

		[ EndStates.PermanentDownloadError ] =
			EndStates.PermanentDownloadError,

		[ EndStates.PermanentError ] =
			EndStates.PermanentError,

		[ EndStates.MissingExpectedXmpDevelopUrl ] =
			EndStates.MissingExpectedXmpDevelopUrl,

		[ EndStates.BadExternalDevelopAuxFileSequence ] =
			EndStates.BadExternalDevelopAuxFileSequence,

	}

	return startStates, finishStates

end

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

local function getEnsureLocalDevelopSettingsForRenderStartFinishStates()

	local PixelPathProviderStateMachine = 
			require "PixelPathProviderStateMachine"

	local DocstoreInfoStates = PixelPathProviderStateMachine.DocstoreInfoStates

	local LocalBinaryPathCheckStates = PixelPathProviderStateMachine.LocalBinaryPathCheckStates

	local startStates = {

		[ LocalBinaryPathCheckStates.RenditionStrategyNeedCheckIfExternalXmpDevelopIsLocal ] =
			LocalBinaryPathCheckStates.RenditionStrategyNeedCheckIfExternalXmpDevelopIsLocal,

	}

	local PixelCacheCheckStates = PixelPathProviderStateMachine.PixelCacheCheckStates

	local EndStates = PixelPathProviderStateMachine.EndStates

	local finishStates = {

		[ PixelCacheCheckStates.NeedCheckForPixelPathInCache ] =
			PixelCacheCheckStates.NeedCheckForPixelPathInCache,

		[ DocstoreInfoStates.UseDefaultRenderSettingsForMissingXmpDevelopRender ] =
			DocstoreInfoStates.UseDefaultRenderSettingsForMissingXmpDevelopRender,

		[ EndStates.NoDownloadableXmpDevelop ] =
			EndStates.NoDownloadableXmpDevelop,

		[ EndStates.MissingExpectedXmpDevelopUrlForRender ] =
			EndStates.MissingExpectedXmpDevelopUrlForRender,

		[ EndStates.PermanentBadAssetIdError ] =
			EndStates.PermanentBadAssetIdError,

		[ EndStates.PermanentDownloadError ] =
			EndStates.PermanentDownloadError,

		[ EndStates.PermanentError ] =
			EndStates.PermanentError,

		[ EndStates.BadExternalDevelopAuxFileSequence ] =
			EndStates.BadExternalDevelopAuxFileSequence,


	}

	return startStates, finishStates

end

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

return {

	addDocStoreInfoStates = addDocStoreInfoStates,

	addLocalBinaryPathCheckStates = addLocalBinaryPathCheckStates,

	addDownloadStates = addDownloadStates,

	addSaveDownloadStates = addSaveDownloadStates,

	addSendDataStates = addSendDataStates,

	addEndStates = addEndStates,

	addTransitions = addTransitions,

	_privateTestExport = {

		getEnsureLocalDevelopSettingsStartFinishStates = 
			getEnsureLocalDevelopSettingsStartFinishStates,

		getEnsureLocalDevelopSettingsForRenderStartFinishStates = 
			getEnsureLocalDevelopSettingsForRenderStartFinishStates,

	}
}
