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

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.

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

	-- RxLua
local Rx = require 'Rx'

	-- WF.core.utils
local WFArguments = require 'WFArguments'
local WFCloseSupport = require 'WFCloseSupport'
local WFLogger = require 'WFLogger'
local WFPlatformInfo = require 'WFPlatformInfo'

	-- WF.core.lua
local WFWorkerThread = require 'WFWorkerThread'

	-- WF.core.table
local WFTableArchiving = require 'WFTableArchiving'

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

local check = assert( WFArguments.check )

local logger = WFLogger( 'WFCatSyncClient' )

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

-- @mark WFCatSyncClient namespace

-- Manages the reference to Sync MessageProcessor where our Sync infrastructure
-- is running on. See WFCatSyncClientImp & WFCatSyncClientBase for the actual 
-- implementation.

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

local syncClientMethods = {

	_syncClientImp = false,
		-- (WFWorkerThread) Reference to the SyncClient WorkerThread instance
	
	WFCloseSupport.addCloseSupportMethods
	
}

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

function syncClientMethods:__init( wfCatalog, optArgs )
	
	check( 'WFCatSyncClient', 'WFCatalog', '?table' )
	
	optArgs = optArgs or {}
	
	local optIndexSpecScript = optArgs.optIndexSpecScript or 
							wfCatalog:indexStore():indexSpecScript() 
								or 'WFCatIndexDefinitions.lua'
	local optSyncClientImpName = optArgs.optSyncClientImpName or 'WFCatSyncClientImp'
	
	local pullerPrefetch
	
	if WFPlatformInfo.isDesktop and WFPlatformInfo.getArchitecture() == 'arm64' then
	
		-- Desktop ARM clients are more-or-less guaranteed to have SSDs. Therefore
		-- we allow the puller to prefetch updates from Oz. We can only do this
		-- for clients that are guaranteed to have fast hard drives.
		
		pullerPrefetch = true
		 
	end
	
	local options = {
		syncClientImpName = optSyncClientImpName,
		serverBase = wfCatalog:ozUser():serverBaseUrl(),
		userId = wfCatalog:ozUserId(),
		userInfoCacheFolder = wfCatalog:ozUser():userInfoCacheFolder(),
		catalogId = wfCatalog:ozCatalogId(),
		catalogDoc = wfCatalog:ozCatalogSpec():catalogDoc(),
		indexSpecScript = optIndexSpecScript,
		rootCatalogPath = wfCatalog:fileSpec():rootPath(),
		docStorePath = wfCatalog:fileSpec():docStorePath(),
		locale = optArgs.locale,
		metadataPullerArgs = optArgs.metadataPullerArgs,
		isSyncClientForProfileCatalog = optArgs.isSyncClientForProfileCatalog,
		pullerPrefetch = pullerPrefetch,
		testMode = optArgs.testMode -- Only used by unit tests.
	}
	
	local optionsString = WFTableArchiving.tableToString( options )
	
	self:setOwned {
		_syncClientImp = WFWorkerThread( 'WFCatSyncClientMessageProcessor.lua', optionsString )
	}

	WFCloseSupport.mustClose( self )
	
end

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

function syncClientMethods:__index( k )

	-- When code attempts to call an undefined method on a WFCatSyncClient object,
	-- this function is called instead. This method will then then generate a
	-- function that will automatically call the correct method on the sync client
	-- worker thread.

	if not k then
		return
	end

	local syncClientImpFn = function( _, ... )
	
		logger:infof( "Now calling WFCatSyncClientImp:%s via WFCatSyncClient", k )
	
		return self._syncClientImp:request( k, ... )
			
	end

	return syncClientImpFn

end

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

return Rx.Class( 'WFCatSyncClient', syncClientMethods )
