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

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


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

	-- WF.core.utils
local KSTableUtils = require 'KSTableUtils'

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

local kNonSyncingLabels = {
	[ 'oz' ] = true, -- set when a revision syncs down from Oz.
	[ '_dontsendtooz' ] = true, -- set when we create a local, non-syncing revision.
	[ '_pendingCommit' ] = true -- set in BYOCR workflows when editing a camera roll image.
}

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

local LrAssetUtils = {}

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

local function isLuaAvailable( name )
  if package.loaded[ name ] then
    return true
  else
    for _, searcher in ipairs( package.searchers or package.loaders ) do
      local loader = searcher( name )
      if type( loader ) == 'function' then
        package.preload[ name ] = loader
        return true
      end
    end
    return false
  end
end

local function optRequire( name ) 
	if isLuaAvailable( name ) then
	 	local result = require( name )
		return result
	else 
		return nil
	end
end


local LrmAssetUtils = optRequire( 'LrmAssetUtils' )
local LriAssetUtils = optRequire( 'LriAssetUtils' )
local WFCatFileSpec = optRequire( 'WFCatFileSpec' )
local WFCatIndexUtils = optRequire( 'WFCatIndexUtils' )
local WFPlatformInfo = optRequire( 'WFPlatformInfo')

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

function LrAssetUtils.hasProxyLocally( docValue )
	
	-- SPAM [matthewj 2019-04-08]: Ideally these would all get consolidated to a single implementation,
	-- but currently each client has a slightly different _localOnly path to the binary files right now
	local hasProxyLocally = ( LrmAssetUtils and LrmAssetUtils.hasProxyLocally( docValue ) ) -- android
					or ( LriAssetUtils and LriAssetUtils.hasProxyLocally( docValue ) ) -- ios
					or ( WFCatFileSpec and not not WFCatFileSpec.getProxyRelativePathFromDocValue( docValue ) ) -- desktop
	
	return hasProxyLocally
	
end

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

function LrAssetUtils.hasMasterLocally( docValue )
	
	-- SPAM [matthewj 2019-04-08]: Ideally these would all get consolidated to a single implementation,
	-- but currently each client has a slightly different _localOnly path to the binary files right now
	local hasMasterLocally =  ( LrmAssetUtils and LrmAssetUtils.hasMasterLocally( docValue ) ) -- android
					or ( LriAssetUtils and LriAssetUtils.hasMasterLocally( docValue ) ) -- ios
					or ( WFCatFileSpec and not not WFCatFileSpec.getOriginalRelativePathFromDocValue( docValue ) ) -- desktop

	return hasMasterLocally
	
end

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

function LrAssetUtils.getlocalOriginalSha256( docValue, localRelativePath )

	local localOriginalSha256

	if WFPlatformInfo.isDesktop then
		if localRelativePath then
			localOriginalSha256 = WFCatFileSpec and WFCatFileSpec.getLocalOriginalSha256( docValue )
		end
	else
		localOriginalSha256 = LrmAssetUtils.getlocalOriginalSha256( docValue )
	end

	return localOriginalSha256

end

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

function LrAssetUtils.getOriginalRelativePathFromDocValue( docValue )

	local originalRelativePath =  ( LrmAssetUtils and LrmAssetUtils.getMasterPath( docValue ) ) -- android and ios

					or ( WFCatFileSpec and WFCatFileSpec.getOriginalRelativePathFromDocValue( docValue ) ) -- desktop

	return originalRelativePath

end

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

function LrAssetUtils.buildOriginalPathFromDocValue( docValue )

	local originalPath =  ( LrmAssetUtils and LrmAssetUtils.buildOriginalPathFromDocValue( docValue ) ) -- android and ios

					or ( WFCatFileSpec and WFCatFileSpec.buildOriginalPathFromDocValue( docValue ) ) -- desktop

	return originalPath

end

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

function LrAssetUtils.doesAssetDocumentHaveLocalBinary( docValue )

	local hasLocalBinary = ( LrmAssetUtils and LrmAssetUtils.doesAssetDocumentHaveLocalBinary( docValue ) ) -- android and ios

				or ( WFCatIndexUtils and WFCatIndexUtils.doesAssetDocumentHaveLocalBinary( docValue ) ) -- desktop

return hasLocalBinary

end

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

function LrAssetUtils.createFullPath( catalogBasePath, localFilePath, binaryType )

	if WFPlatformInfo.isDesktop then 
		error( "not implemented on desktop" )
	end

	return LrmAssetUtils.createFullPath( catalogBasePath, localFilePath, binaryType )

end

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

function LrAssetUtils.hasNonSyncingLabel( docValue )

	local labels = KSTableUtils.derefOpt( docValue, '_labels' )

	if labels then

		for nonSyncingLabel in pairs( kNonSyncingLabels ) do

			if labels[ nonSyncingLabel ] then
				return true
			end

		end

	end

	return false

end

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

function LrAssetUtils.isLatestMetadataUploaded( docValue )

	local spm = docValue and docValue._serverProvidedMetadata

	if docValue._deleted and spm and spm.deleted_by then

	 	-- When Oz sends a tombstone it contains no links and no revision_ids
		-- so we can't use those to tell whether Oz has the deletion (we can't use 
		-- their absence either because if it's not on Oz yet it won't have them
		-- either). However, Oz does send a deleted_by field down in the tombstone
		-- so it's presence should indicate Oz knows it's been deleted.
		return true

	end

	if LrAssetUtils.hasNonSyncingLabel( docValue ) then

		-- We don't send document updates to Oz that contain specific labels.
		-- Therefore, the metadata should be considered uploaded because we have
		-- no intention of syncing it.

		return true

	end

	local links = KSTableUtils.derefOpt( spm, 'links' )

	-- Do we have nothing on Oz yet?

	if not links then
		return false
	end

	if spm then

		local revId = docValue._revId

		local revIds = spm.revision_ids

		if revIds then

			local cnt = #revIds

			if cnt == 0 then
				-- SPAM [matthewj 2016-09-02]: if the revision_ids table is present but
				-- empty this is likely an older non-asset type doc (e.g. album) from
				-- Oz which did not traditionally have revision ids. We will consider
				-- these as synced for UI purposes as in most cases it will be. However,
				-- the first local change to the doc will not trigger the UI status to
				-- move to 'syncing' as the revision id table will still be empty. Once
				-- this actually syncs to Oz and back the revision_ids array will no
				-- longer be empty and all subsequent changes should correctly reflect
				-- in changes to the sync status for the UI
				return true
			end

			-- if local _revId can be found in revision_ids array tracked by Oz
			-- the latest metadata is uploaded

			for i = cnt, 1, -1 do

				local ozRevId = revIds[ i ]
				if revId == ozRevId then
					return true
				end

			end

		end

	end

	return false

end

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

LrAssetUtils._TEST_nonSyncingLabels = kNonSyncingLabels

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

return LrAssetUtils
