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

WFCatImportManifestRootAlbumAssetsProcessor.lua

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

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

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

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

	-- WF.oz_client.managed_catalog
local WFCatAlbums = require 'WFCatAlbums'
local WFConfiguration = require 'WFConfiguration'

	-- WF.oz_client.managed_catalog.import
local WFCatImportManifestConstants = require 'WFCatImportManifestConstants'
local WFCatImportManifestProcessorBase = require 'WFCatImportManifestProcessorBase'
local DONT_ADD_STACKS_IN_ROOT_ALBUM = WFConfiguration.Migrate.DontAddStacksInRootAlbum
--------------------------------------------------------------------------------

local kAlbumAssetBatchSize = 100

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

local function updateAlbumAssetStatusWithIds( manifestStatusDatabase, assetLocalIdForOzAssetId, albumAssetsInfo, success )
	
	local statusWithOzIds = {}
	local status = success and WFCatImportManifestConstants.status.success or WFCatImportManifestConstants.status.failure
	
	for assetId, oz_id in pairs( albumAssetsInfo ) do
		statusWithOzIds[ #statusWithOzIds + 1 ] = {
			local_id = assetLocalIdForOzAssetId[ assetId ],
			status = status,
			oz_id = oz_id,
		}
	end
	
	return manifestStatusDatabase:writeData( 'addRootAlbumAssetStatus', statusWithOzIds )
		:ignoreElements()
	
end

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

local function updateAlbumAssetStatus( manifestStatusDatabase, assetOzIdToLocalId, success )
	
	local statusData = {}
	local status = success and WFCatImportManifestConstants.status.success or WFCatImportManifestConstants.status.failure
	
	for _, assetLocalId in pairs( assetOzIdToLocalId ) do
		statusData[ #statusData + 1 ] = {
			local_id = assetLocalId,
			status = status,
		}
	end
	
	return manifestStatusDatabase:writeData( 'addRootAlbumAssetStatus', statusData )
		:ignoreElements()
	
end

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

local function reportAlbumAssetErrorEntries( self, messageHandler, assetOzIdToLocalId )
	
	local errData = {}	
	
	for _, assetLocalId in pairs( assetOzIdToLocalId ) do
		errData[ #errData + 1 ] = { assetLocalId }
	end
	
	self:_sendMessage( messageHandler, WFCatImportManifestConstants.messages.rootAlbumAssetsCreateError.code, errData )	
	self:_updateError( messageHandler, #errData )
end

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

local function addAllAssetsToAlbum( self, catalog, idCache, manifestStatusDatabase, messageHandler, albumOzId )

	local allAssetsIdToOzIdMap = idCache:getAllForSet( WFCatImportManifestConstants.idCacheSets.assets ) or {}

  --[[NMB -5371  Issue: Migrated Stacks are not accessible via Root Album 
     We were only adding assets, but not stacks to the root album
	 With this fix - Fetching all stacks data allStacksIdToOzMap, appending it to table allAssetsIdToOzIdMap, which eventually is added to root album]]
	if not DONT_ADD_STACKS_IN_ROOT_ALBUM then 
		local allStacksIdToOzMap = idCache:getAllForSet( WFCatImportManifestConstants.idCacheSets.stacks ) or {}
		table.foreach(allStacksIdToOzMap, function(k,v) allAssetsIdToOzIdMap[k] = v end)
	end
	return manifestStatusDatabase:readData( "countAssetsStatus", { status = WFCatImportManifestConstants.status.success } )
		
		:map( function( results )
			if results[ 1 ] then
				return results[ 1 ].count
			end
		end )
		:tap( function( count )
			
			assert( type( count ) == 'number' )
			
			self._totalCount = count
		end )
		
		:flatMap( function()
			
			return Observable.create( function( observer )
	
				local assetOzIds = {}
				local assetOzIdToLocalId = {}
				
				for localId, ozId in pairs( allAssetsIdToOzIdMap ) do
			
					assetOzIds[ #assetOzIds + 1 ] =  ozId
					assetOzIdToLocalId[ ozId ] = localId
					
					-- If we have enough to fire, then fire.
					if #assetOzIds == kAlbumAssetBatchSize then
						
						observer:onNext( assetOzIds, assetOzIdToLocalId )
						assetOzIds = {}
						assetOzIdToLocalId = {}
						
					end
				end
				
				-- Have some more elements left
				if #assetOzIds > 0 then
					observer:onNext( assetOzIds, assetOzIdToLocalId )
				end
				
				observer:onCompleted()
				
			end )
		end )
		
		:flatMap( function( assetOzIds, assetOzIdToLocalId )
			
			return WFCatAlbums.addAssetsToAlbumGivenDocIds( catalog, albumOzId, assetOzIds, {}, false )
					
				:flatMap( function( albumAssetsInfo )
					return updateAlbumAssetStatusWithIds( manifestStatusDatabase, assetOzIdToLocalId, albumAssetsInfo, true )
				end )
				
				:tapOnCompleted( function()
					self:_updateSuccess( messageHandler, #assetOzIds )
				end )
				
				:catch( function()
					reportAlbumAssetErrorEntries( self, messageHandler, assetOzIdToLocalId )
					return updateAlbumAssetStatus( manifestStatusDatabase, assetOzIdToLocalId, false )
				end ) 
			
		end )

end

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

local WFCatImportManifestRootAlbumAssetsProcessor = {
	
	WFCatImportManifestProcessorBase,
}

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

function WFCatImportManifestRootAlbumAssetsProcessor:__init()

	self._stageName = WFCatImportManifestConstants.stageNames.rootAlbumAssets

	self._messageCodeCompleted = WFCatImportManifestConstants.messages.rootAlbumAssetsProcessingComplete.code
	self._messageCodeErrorCount = WFCatImportManifestConstants.messages.rootAlbumAssetsProcessingErrorCount.code
	self._messageCodeGenericError = WFCatImportManifestConstants.messages.rootAlbumAssetsProcessingError.code
end

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

function WFCatImportManifestRootAlbumAssetsProcessor:setup( catalog, manifestDatabase, manifestStatusDatabase, idCache, messageHandler )

	return self:WFCatImportManifestProcessorBase_setup( catalog, 
		manifestStatusDatabase, idCache, messageHandler, 'selectRootAlbumAssetsStatus' )

end

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

function WFCatImportManifestRootAlbumAssetsProcessor:processImpObservable( catalog, profileCatalog, wfCatSynchronizer, 
			manifestDatabase, manifestStatusDatabase, idCache, messageHandler, contextInfo )
	
	local allPhotosAlbumOzId = idCache:getOzIdForLocalId( WFCatImportManifestConstants.idCacheSets.albums, WFCatImportManifestConstants.kManifestAllPhotoAlbumLocalId )
	
	if not allPhotosAlbumOzId then
		return Observable.throw("All-Photos album missing")
	end
	
	return addAllAssetsToAlbum( self, catalog, idCache, manifestStatusDatabase, messageHandler, allPhotosAlbumOzId )
		
		:ignoreElements()
		
end

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

return Rx.Class 'WFCatImportManifestRootAlbumAssetsProcessor'( WFCatImportManifestRootAlbumAssetsProcessor )
