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

WFOzFileLock.lua

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

ADOBE CONFIDENTIAL
------------------
Copyright 2012 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.logging
local WFLogger = require 'WFLogger'

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

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


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

local check = WFArguments.check

local WFOzFileLock = 'WFOzFileLock'


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

local logger = WFLogger 'WFOzFileLock'
--	:setLevel 'debug'

local BabluEP = WFWorkerThread( 'BabluImp.lua' )


--============================================================================--
--[[!
	\class WFOzFileLock
	\brief Provides the ability to lock a file, preventing it
	from being purged or moved between documents and caches.
	
	Create an object of this type to lock the associated file, and close
	the object explicitly when you no longer need to protect the file.
--]]

-- @mark WFOzFileLock class

local fileLockSessionMethods = {

	_catalogId = false,
		-- (string) catalog ID

	_filePath = false,
		-- (string) path to the file we're locking
	
	_lockP = false,
		-- (P< true >) confirmation of lock from purge agent
	
	WFCloseSupport.addCloseSupportMethods,

}

--------------------------------------------------------------------------------
--[[!
	\brief Constructs a file lock object.
	
	\param ozCatalogService (OzCatalogService) The catalog to which the file belongs.
	\param filePath (string) The full path to the file to protect.
--]]

function fileLockSessionMethods:__init( --[[OzCatalogService]] ozCatalogService,
										--[[string]] filePath )

	check( WFOzFileLock, 'OzCatalogService | OzCatalogServiceImp', 'string' )

	WFCloseSupport.mustClose( self )

	logger:debugf( "Requesting lock on file at path %s", filePath )

	self._catalogId = false
	self._filePath = filePath
	
	self._lockP = 
		ozCatalogService:getCatalogIdP()
		
		:observeP( function( _, catalogId )
		
			self._catalogId = catalogId
			
		end )
		
		:mapDataP_new( function( catalogId )
		
			return BabluEP:requestP( 'lockFileAtPath', catalogId, filePath )
			:mapP( function( status, result )
			
				logger:debugf( "File lock request for path %s resolved with status %s result %s",
							   filePath, status, result )
	
				if status == 'data' and not result then
					return 'error', "File no longer exists"
				else
					return status, result
				end
			
			end )
			
		end )

	self._lockP:whenResolvedDo( function() end ):attachTo( self )

end

--------------------------------------------------------------------------------
--[[!
	\brief Retrieves (as a Promise) the path to the file that this lock object
		is associated with.
	
	\return <code>P< filePath ></code> A Promise that resolves to
		the full path when the file lock is confirmed (or to an error otherwise).
--]]

function fileLockSessionMethods:lockedFilePathP()

	return self._lockP
		:mapDataP( function()
			return 'data', self._filePath
		end )

end

--------------------------------------------------------------------------------
--[[!
	\brief Closes this ojbect, releasing the file lock.
--]]

function fileLockSessionMethods:close()

	logger:debugf( "Releasing lock on file at path %s", self._filePath )

	BabluEP:requestP( 'unlockFileAtPath', self._catalogId, self._filePath )
		:runUntilDone()
	
end

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

return Rx.Class 'WFOzFileLock'( fileLockSessionMethods )
