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

LrClassicCatalog.lua

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

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

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

	-- RxLua
local Rx = require 'Rx'

local KSTableUtils = require 'KSTableUtils'
local WFArguments = require 'WFArguments'
local WFCatalogBase = require 'WFCatalogBase'
local WFObjectProxy = require 'WFObjectProxy'
local WFCatStacksProcessor = require 'WFCatStacksProcessor'
local NmbSimpleDocStoreUpdater = require 'NmbSimpleDocStoreUpdater'
local WFCatSyncStatus = require 'WFCatSyncStatus'

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

local check = assert( WFArguments.check )

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

local lrClassicCatalogPrototype = {
	
	WFCatalogBase,
		--superclass
	
	_initOptArgs = false,
		-- (table) optional args passed in at __init (needed for __inited)

	_docStoreUpdater = false,
		-- (NmbSimpleDocStoreUpdater) Allows for simple updating (format changes) of documents
		
	_stacksProcessor = false,
		-- (WFCatStacksProcessor) Processes incoming stacks to ensure they're formatted correctly
		-- for display
	
	_connectorPublisher = false,
	
	class = {},
	
	_searchSchema = false,
	
}

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

--[[!
	\brief Creates a LrClassicCatalog.
	
	\param ozCatalogSpec (WFCatSpec) specification for the catalog user and catalogID
	\param rootCatalogPath (string) root directory under which to store catalog related files
	\param optArgs (table) optional args for doc store index store creation. These are in addition
			to any optional args allowed by WFCatalogBase

]]--

function lrClassicCatalogPrototype:__init( ozCatalogSpec, rootCatalogPath, optArgs )
	
	check( 'LrClassicCatalog', 'WFCatSpec', 'string', '?table' )
	
	self._initOptArgs = optArgs or {}
	
	-- these arguments are returned to be used in the superclass (WFCatalog) init
	return ozCatalogSpec, rootCatalogPath, optArgs
	
end

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

--[[ 
	\brief Completes initialization of the lrClassicCatalog after the superclass has been initialized
]]--
function lrClassicCatalogPrototype:__inited( )

	check( 'LrClassicCatalog' )

	if not self._initOptArgs.isSyncClientForProfileCatalog then

		if not self._initOptArgs.syncClientBaseInstance then
		
			-- Within LrD, the NmbCatalog object is created in two different places: Once in the user model,
			-- and once in the sync client thread. The following code should only be initialized when we
			-- create NmbCatalog object from the user model; it's not necessary for the following tasks
			-- to be set up more than once.

			local docStoreUpdater = NmbSimpleDocStoreUpdater( self._docStore, self._indexStore, self._wfCatFileSpec )
			
			local stacksProcessor = WFCatStacksProcessor( self._docStore, self._indexStore )
			
			self:setOwned {
				_docStoreUpdater = docStoreUpdater,
				_stacksProcessor = stacksProcessor,
			}

		end

	end
	
end

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

function lrClassicCatalogPrototype:searchSchema()

	check( 'LrClassicCatalog' )
	return self._searchSchema

end

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

function lrClassicCatalogPrototype:getDocStoreUpdater()

	check( 'LrClassicCatalog' )
	return self._docStoreUpdater

end

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

function lrClassicCatalogPrototype:getCatalogProfileCache()

	check( 'LrClassicCatalog' )
	return self._catalogProfileCache

end

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

function lrClassicCatalogPrototype:setCatalogName( catalogName )

	check( 'LrClassicCatalog', '+string' )
	
	local catalogId = self:ozCatalogSpec():catalogId()
	
	return self._docStore:docValue( catalogId )
		:map( function( maybeCatalogDoc )
			if maybeCatalogDoc._empty then
				error( "Catalog document missing from catalog" )
			end
			return maybeCatalogDoc
		end )
		:flatMap( function( catalogDoc )

			return self._docStore:applyOverlay {
				_id = catalogId,
				name = catalogName,
			}
			
		end )
		
end

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

function lrClassicCatalogPrototype:getCatalogName()

	local catalogId = self:ozCatalogSpec():catalogId()
	
	return self._docStore:ongoingDocValue( catalogId )
		:filter( function( maybeCatalogDoc ) 
			return not maybeCatalogDoc._empty
		end )
		:map( function( catalogDoc )
			return KSTableUtils.derefOpt( catalogDoc, 'name' )
		end )
		:distinctUntilChanged()

end

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

function lrClassicCatalogPrototype:overlayUniversalCatalogDocumentSetting( settingKey, settingValue )
	
	check( 'LrClassicCatalog', '+string' )
	local catalogId = self:ozCatalogSpec():catalogId()
	
	return self._docStore:docValue( catalogId )
		:map( function( maybeCatalogDoc )
			if maybeCatalogDoc._empty then
				error( "Catalog document missing from catalog" )
			end
			return maybeCatalogDoc
		end )
		:flatMap( function( catalogDoc )
	
			local overlay = {
				_id = catalogId,
				[ "settings" ] = {
					[ 'universal' ] = {
						[ settingKey ] = settingValue
					}
				},
			}
			--overlay = WFCatUtils.addUserUpdatedFields( overlay )
			
			return self._docStore:applyOverlay( overlay )
			
		end )
	
end

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

function lrClassicCatalogPrototype:getUniversalCatalogDocumentSetting( settingKey )
	
	check( 'LrClassicCatalog', '+string' )
	
	return self._docStore:ongoingDocValue( self:ozCatalogSpec():catalogId() )
		:map( function( maybeCatalogDoc )
			if maybeCatalogDoc._empty then
				return nil
			end
			return KSTableUtils.derefOpt( maybeCatalogDoc, 'settings', 'universal', settingKey )
		end )
		
end 

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

--[[
	\brief Get a notification( return true ) once initial sync has completed for LrClassic
	
]]--

function lrClassicCatalogPrototype:waitForInitialSyncCompleted( )

	return WFCatSyncStatus.isDoingInitialSync( self )
		:filter ( function( isDoingInitialSync )
			return not isDoingInitialSync
		end )
		:take( 1 )
end

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

local LrClassicCatalog_class = Rx.Class( 'LrClassicCatalog', lrClassicCatalogPrototype )

return WFObjectProxy( 'WFCatalog', LrClassicCatalog_class, nil, true )
