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

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'

	-- WF.sqlite.doc_store

local WFOldWFDocStoreReader = require 'WFOldWFDocStoreReader'

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

-- @mark WFOldWFDocStoreMigratorImp namespace

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

local underscoreByte = string.byte( '_' )

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

local WFOldWFDocStoreMigratorImpMethods = {

	_userId = false,
		-- (string) User id
		
	_rxDocStoreImp = false,
		-- (WFRxDocStoreImp)
		
	_wfDocStoreReader = false,
		-- (WFOldWFDocStoreReader)
		
	WFCloseSupport.addCloseSupportMethods,
}

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

function WFOldWFDocStoreMigratorImpMethods:__init( rxDocStoreImp, userId )

	WFArguments.check( 'WFOldWFDocStoreMigratorImp', 'WFRxDocStoreImp', 'string' )

	self._userId = userId
	
	-- Note [immisch 2021-05-18]: WF-1542 make the WFRxDocStoreImp compatible with the old return format
	rxDocStoreImp._TEST_unpackDocValue = true
	
	self:setOwned {
		
		_rxDocStoreImp = rxDocStoreImp,
		
		_wfDocStoreReader = WFOldWFDocStoreReader( userId )
	}
	
end

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

local function migrateLinksTable( links )

	if not links then
		return
	end
	
	for k, v in pairs( links ) do
	
		local href = v.href
		
		if href then
		
			v.href = href:gsub( '^/v1.0', '/v2' )
			
		end
	end
	
end

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

local function makeRxDocFromOzDocRow( rawOzDocRow )
									  
	local result = {
		_id = rawOzDocRow._id,
		type = rawOzDocRow.type,
	}
	
	if rawOzDocRow._slot ~= 'main' then
	
		return
	end
	
	for k, v in pairs( rawOzDocRow ) do
	
		if k:byte( 1 ) ~= underscoreByte then
			result[ k ] = v
		end
		
	end
	
	result[ 'link_templates' ] = nil
	
	migrateLinksTable( result.links )
	
	result[ 'id' ] = result._id
	
	if result.type == 'catalog' then
	
		local owner = result.owner
		
		if owner then
		
			owner[ 'id' ] = owner._id
			owner._id = nil
			
			migrateLinksTable( owner.links )
			
		end
	
	end
	
	return result
	
end

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

local function getCatalogDocValue( newDocRows )

	for i, v in ipairs( newDocRows ) do
	
		if v.type == 'catalog' and ( v.subtype == 'lightroom' or v.subtype == 'x-lightroom' ) then
		
			return v
			
		end
		
	end
	
	return nil
	
end

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

local function getUserDocValue( newDocRows )

	for i, v in ipairs( newDocRows ) do
	
		if v.type == 'user' then
		
			return v
			
		end
		
	end
	
	return nil
	
end

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

function WFOldWFDocStoreMigratorImpMethods:readBatchAndGenerateWFRxDocs( fromChangeCounter )

	local rawOzDocs = self._wfDocStoreReader:readDocumentBatch( fromChangeCounter )
	
	local result = {}
	local nResults = 0
	
	local function appendResult( docValue )
		nResults = nResults + 1
		result[ nResults ] = docValue
	end
	
	for i = 1, #rawOzDocs do
	
		local rawOzDoc = rawOzDocs[ i ]

		local migratedDoc = makeRxDocFromOzDocRow( rawOzDoc )
		
		if migratedDoc then
			appendResult( migratedDoc )
		end
		
	end
	
	return result, nResults, rawOzDocs.continueFrom
	
end

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

function WFOldWFDocStoreMigratorImpMethods:processNextBatch( fromChangeCounter )

	local newDocRows, migratedDocumentCount, newFromChangeCounter =
		self:readBatchAndGenerateWFRxDocs( fromChangeCounter )
	
	if #newDocRows > 0 then
	
		self._rxDocStoreImp:bulkSetDocValue( newDocRows )
		
		local catalogDocValue = getCatalogDocValue( newDocRows )
		local userDocValue = getUserDocValue( newDocRows )
		
		if catalogDocValue and userDocValue then
		
			local userOverlay = {
				_id = userDocValue._id,
				_localOnly = {
					managedCatalogId = catalogDocValue._id,
				}
			}
			
			self._rxDocStoreImp:applyOverlay( userOverlay )
			
		end
		
	end
	
	return #newDocRows > 0, newFromChangeCounter, migratedDocumentCount
	
end

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

function WFOldWFDocStoreMigratorImpMethods:runMigration()

	local fromChangeCounter = 0
	local hadDocsToProcess = true
	local migratedDocumentCount = 0
		
	while hadDocsToProcess do
	
		local docCount
		hadDocsToProcess, fromChangeCounter,
			docCount = self:processNextBatch( fromChangeCounter )
			
		migratedDocumentCount = migratedDocumentCount + docCount
			
	end
		
	return migratedDocumentCount
	
end

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

function WFOldWFDocStoreMigratorImpMethods:runUntilDone()

	self:runMigration()
	
	self._rxDocStoreImp:close()
	
	return Rx.Observable.just( true )
	
end

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

function WFOldWFDocStoreMigratorImpMethods:sourceDocumentCount()

	return self._wfDocStoreReader:sourceDocumentCount()
	
end

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

return Rx.Class( 'WFOldWFDocStoreMigratorImp', WFOldWFDocStoreMigratorImpMethods )
