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

WFCatPendingcommitHandler.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.

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

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

local KSIdGenerator = require 'KSIdGenerator'
local WFCloseSupport = require 'WFCloseSupport'
local WFRxContinuousTask = require 'WFRxContinuousTask'

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

-- @mark Class Methods

local WFCatPendingCommitHandler = {
	_catalog = false,
		--(WFCatalog)

	_purgeAgent = false,

	_cleanupTask = false,
		--(WFRxContinuousTask)

	_prevChangeCounter = false,
		--(string) The change counter of the doc store the last time the cleanup task executed

	WFCloseSupport.addCloseSupportMethods,

}

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

function WFCatPendingCommitHandler:__init( wfCatalog, purgeAgent )

	self._catalog = wfCatalog
	self._purgeAgent = purgeAgent

end

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

function WFCatPendingCommitHandler:maybeInitialzeCleanupTask()

	local cleanFn = function()

		local currChangeCounter = self._catalog:docStore():changeCounter()

		-- If there have been no changes since the last run, there is nothing to clean up
		if currChangeCounter ~= self._prevChangeCounter then

			self._prevChangeCounter = currChangeCounter

			return self:cleanup()

		end

		return Observable.just( nil )

	end

	if not self._cleanupTask then

		self._cleanupTask = WFRxContinuousTask( 'WFCatPendingCommitHandler', cleanFn )

		self._cleanupTask:startContinuousTask()

	end

end

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

function WFCatPendingCommitHandler:cleanup() -- Expose this as a oneoff testing handler

	if WFCloseSupport.hasBeenOrWillBeClosed( self._catalog ) then

		return Observable.just( nil )

	end

	return self._catalog:docStore():getIdsOfDocsWithLabel('_pendingCommit')
		:flatMap( function( docIds )

			return Observable.from( docIds )

		end )
		:filter( function( docId )
			return not self._purgeAgent:isLocked( docId )
		end)
		:scan( function ( acc, docId )

			acc[ #acc + 1 ] = docId
			return acc

		end, {} )
		:takeLast( 1 )
		:flatMap( function( docIds )

			if not docIds or not next( docIds ) then

				return Observable.just( false )

			end

			local labelRemoveOverlays = {}

			for _, docId in pairs(docIds) do

				local overlay = {
					_id = docId,
					_newRevId = KSIdGenerator.uuidInLowercaseHex()
				}

				labelRemoveOverlays[ #labelRemoveOverlays + 1 ] = overlay
			end

			return self._catalog:docStore():bulkApplyOverlay( labelRemoveOverlays )

		end )
end

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

function WFCatPendingCommitHandler:startCleanTask()

	self:maybeInitialzeCleanupTask()

	return Observable.just( true )
end

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

function WFCatPendingCommitHandler:close()

	if self._cleanupTask then

		self._cleanupTask:stopContinuousTask()
		self._cleanupTask = nil

	end

end

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

return Rx.Class 'WFCatPendingCommitHandler'( WFCatPendingCommitHandler )
