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

WFCatSyncStatusModel.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
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'
	-- RxLua
local WFRxScheduler = require 'WFRxScheduler'

	-- WF.oz_client.managed_catalog.sync
local WFCatStorage = require 'WFCatStorage'
local WFCatSyncStatus = require 'WFCatSyncStatus'

	-- lightroomcc.file_management
local NmbStorage = require 'NmbStorage'

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

local WFCatSyncStatusModel = {}

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

function WFCatSyncStatusModel.storageEntitlement( wfCatalog )
	
	return WFCatStorage.storageEntitlement( wfCatalog )

end

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

function WFCatSyncStatusModel.localStorage( wfCatalog )
	
	local refreshLocalStorageCountAtMost = 90
		-- At most, recalculate the size of local storage every N seconds.
		
	return wfCatalog:docStore():changeCounter()
	
		:calm( refreshLocalStorageCountAtMost, WFRxScheduler.sharedScheduler() )
	
		:flatMapLatest( function() 
			return NmbStorage.localStorage( wfCatalog )
		end )
		
end

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

local function makeWithFirstValidCatalog( wfCatalogStream, defaultValue )

	return function( fn, ... )

		local params = { ... }
		local nParams = select( '#', ... )

		return wfCatalogStream

			:flatMapLatest( function( wfCatalog )
				if not wfCatalog then
					return Rx.Observable.just( defaultValue )
				end

				return fn( wfCatalog, unpack( params, 1, nParams ) )
			end )

	end

end

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

function WFCatSyncStatusModel.makeStorageModel( wfCatalogStream )
	
	local f = makeWithFirstValidCatalog( wfCatalogStream, {} )
	
	return {
		value = {
			oz = f( WFCatSyncStatusModel.storageEntitlement, {} ),
			localPC = f( WFCatSyncStatusModel.localStorage, {} ):startWith( {} ),
					-- NMB-5704: Added the startWith( {} ) so that full storage model isn't 
					-- delayed by the time to calc localStorage. If the SyncActivityPopup
					-- or the model cached the previous values, that would be better, but 1.0
					-- has deadlines and nowhere in the app currently shows the localStorage
					-- values. If they do, they'll get no results a few seconds before the 
					-- real results and may flash.
		}
	}

end

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

function WFCatSyncStatusModel.makeSyncStatusModel( wfCatalogStream )
	
	local f = makeWithFirstValidCatalog( wfCatalogStream, {} )
		
	return {
		value = f( WFCatSyncStatus.getSyncStatusForAssets, {} )
	}

end

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

function WFCatSyncStatusModel.makeAssetSyncStatusModel( wfCatalogStream, assetIds )

	local f = makeWithFirstValidCatalog( wfCatalogStream, {} )
	
	local syncStatusColumnName = WFCatSyncStatus.getSyncStatusColumnName()
	
	local syncStatusAndVolumeInfos = wfCatalogStream:filter( function( wfCatalog ) return not not wfCatalog end )
		:flatMapLatest( function( wfCatalog )
			local imageLocalIds
			if assetIds and type( assetIds[ 1 ] ) == 'number' then
				imageLocalIds = Rx.Observable.just( assetIds )	
			else
				imageLocalIds = wfCatalog:docStore():bulkDocIdToLocalIdAsMap( assetIds )
					:map( function( assetIdToLocalIdMap )
						local localIds = {}
						for _, assetId in ipairs( assetIds ) do
							localIds[ #localIds + 1 ] = assetIdToLocalIdMap[ assetId ]
						end
						return localIds
					end )
			end

			return imageLocalIds
				:flatMapLatest( function( localIds )
					return wfCatalog:indexStore():query {
					sql = string.format( [[SELECT %s, originalVolumeGuid, proxyVolumeGuid FROM TEMP_ids 
								JOIN assetPathsAndInfo ON assetPathsAndInfo.localId = TEMP_ids.docId
								JOIN asset_sync_status_ui ON asset_sync_status_ui.docId = TEMP_ids.docId]],
								syncStatusColumnName ),
					tempIds = localIds,
					calm = 1,
				}
				end )
			end )
			:replay( nil, 1 )
			:refCount()
	
	return {
		value = {
			syncStatus = f( WFCatSyncStatus.getCombinedAssetStatusAsStr, syncStatusAndVolumeInfos ),
			localFileType = f( WFCatSyncStatus.getCombinedLocalFileTypeAsStr, syncStatusAndVolumeInfos ),
			ozStatus = f( WFCatSyncStatus.getCombinedOzStatusFromIdsAsStr, assetIds ),                                                         
			markedForOfflineUse = f( WFCatSyncStatus.getCombinedMarkedForOfflineUse, syncStatusAndVolumeInfos ),
		},
	}

end

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

return WFCatSyncStatusModel
