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

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

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

local KSPathUtils = require "KSPathUtils"
local KSStringUtils = require "KSStringUtils"
local KSTableUtils = require "KSTableUtils"
local KSIdGenerator = require 'KSIdGenerator'

local WFArguments = require "WFArguments"
local WFFileUtils = require "WFFileUtils"
local WFLogger = require "WFLogger"
local WFPlatformInfo = require "WFPlatformInfo"

	-- WF.oz_client.sync_engine
local WFOzSyncConstants = require 'WFOzSyncConstants'
local logger = WFLogger "OzFilePaths"

local derefOpt = assert( KSTableUtils.derefOpt )

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

local OzFilePaths = {}


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

--[[!
	\brief construct a file path for the standard originalFolderDocuments path, based
	on a catalog ID. This is the standard base for relative paths.
	
	\param catalogId the GUID id for the catalog
	\return (string) the file path
--]]
function OzFilePaths.getCatalogBasePath( catalogId )

	WFArguments.check( "string" )
	
	local documentsDir = KSPathUtils.getStandardFilePath 'carouselDocuments'
	
	return KSPathUtils.child( documentsDir, catalogId )
		
end

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

--[[!
	\brief Construct an absolute path from a relative path within the Catalog Path
	
	\param catalogId (string) the GUID id for the catalog
	\param path (string) the relative path within the Catalog Path
	\return (string) the absolute file path
--]]
function OzFilePaths.getAbsolutePathInCatalog( catalogId, path )

	WFArguments.check( 'string', 'string' )
	
	local catalogPath = OzFilePaths.getCatalogBasePath( catalogId )
	
	return KSPathUtils.child( catalogPath, path )
		
end

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

--[[!
	\brief construct a file path for the standard originalFolderDocuments path, based
	on a catalog ID
	
	\param catalogId the GUID id for the catalog
	\return (string) the file path
--]]
function OzFilePaths.getStandardOriginalFolderDocumentsPath( catalogId )

	WFArguments.check( "string" )

	if not WFPlatformInfo.isAndroid then
		return KSPathUtils.child( OzFilePaths.getCatalogBasePath( catalogId ), 'Originals' )
	end

	local documentsDir = KSPathUtils.getStandardFilePath 'carouselDocuments'

	local originalsFolderDocuments = documentsDir

	if not WFOzSyncConstants.isGlobalDocumentId( catalogId ) then

		originalsFolderDocuments = KSPathUtils.child( documentsDir, catalogId )

	end

	originalsFolderDocuments = KSPathUtils.child( originalsFolderDocuments, "Originals" )

	return originalsFolderDocuments

end

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

--[[!
	\brief construct a file path for the standard originalFolderCaches path, based
	on a catalog ID
	
	\param catalogId the GUID id for the catalog
	\return (string) the file path
--]]
function OzFilePaths.getStandardOriginalFolderCachesPath( catalogId )

	WFArguments.check( "string" )
	
	local cachesDir = KSPathUtils.getStandardFilePath 'carouselCaches'
	
	local originalsFolderCaches = KSPathUtils.child( cachesDir, catalogId )
	originalsFolderCaches = KSPathUtils.child( originalsFolderCaches, "Originals" )
	
	return originalsFolderCaches
	
end

--[[!
	\brief construct a file path for the standard originalFolderCaches path, based
	on a catalog ID

	\param docId the document id
	\param catalogIdForCreation if set, the intermediate directory should be created
	\return (string) the file path
--]]
function OzFilePaths.getRelativeBlobPath( docId, catalogIdForPathCreation )

	WFArguments.check( "string", "?string" )

	local path = KSPathUtils.child( 'blobs', string.sub( docId, 1, 2 ) )
	path = KSPathUtils.child( path, docId )

	if catalogIdForPathCreation then
		local absPath = KSPathUtils.child( OzFilePaths.getCatalogBasePath( catalogIdForPathCreation ), path )

		if not pcall( WFFileUtils.mkdir, absPath ) then
			logger:errorf( "could not create asset directory %s for %s", absPath, docId )

			return nil
		end
	end

	return path
end

--------------------------------------------------------------------------------
--[[!
	\brief construct a relative and absolute file path the external xmp develop document, 
	based on a catalog ID and the sha256 of the contents.

	\param catalogId the GUID id for the catalog
	\param docValue the docValue
	\param sha256 the sha256 of the develop settings
	\param createDir set to true if the intermediate directory should be created
	\return (string, string) the relative and absolute file name of the external develop settings
--]]
function OzFilePaths.getXmpDevelopPath( catalogId, docValue, optSha256, optCreateDir )

	WFArguments.check( "string", "table", "?string", "?boolean" )

	local documentsPath = KSPathUtils.getStandardFilePath( 'carouselDocuments' )

	local sha256 = optSha256 or derefOpt( docValue, 'develop', 'xmpCameraRaw', 'sha256' )

	local xmpDevelopRelPath, xmpDevelopAbsPath

	if WFPlatformInfo.isAndroid then

		if not WFOzSyncConstants.isGlobalDocumentId( catalogId ) then
			xmpDevelopRelPath = catalogId
		else
			xmpDevelopRelPath = ''
		end

		xmpDevelopRelPath = KSPathUtils.child( xmpDevelopRelPath, "xmp_develop" )

		local xmpDevelopFileName = sha256
		local spaceId = docValue._spaceId

		if spaceId and spaceId ~= "" then
			xmpDevelopFileName = xmpDevelopFileName .. '-' .. spaceId
		end

		xmpDevelopRelPath = KSPathUtils.child( xmpDevelopRelPath, xmpDevelopFileName .. '.rdf' )
	
		xmpDevelopAbsPath = KSPathUtils.child( documentsPath, xmpDevelopRelPath )
	
	elseif WFPlatformInfo.isiOS then
	
		xmpDevelopRelPath = OzFilePaths.getRelativeBlobPath( docValue._id, catalogId )

		xmpDevelopRelPath = KSPathUtils.child( xmpDevelopRelPath, 'xmp_' .. sha256 .. '.rdf' )
	
		xmpDevelopAbsPath = KSPathUtils.child( documentsPath, catalogId )
		
		xmpDevelopAbsPath = KSPathUtils.child( xmpDevelopAbsPath, xmpDevelopRelPath )
	
	else
		error( 'getXmpDevelopPath is only available on Mobile' )
	end

	if optCreateDir then

		local parentPath = KSPathUtils.parent( xmpDevelopAbsPath )

		WFFileUtils.mkdir( parentPath )

	end

	return xmpDevelopRelPath, xmpDevelopAbsPath

end

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

--[[!
	\brief construct a relative and absolute file path the watermark graphic file,
	based on a watermark ID and the filename.

	\param catalogId the GUID id for the catalog
	\param docValue the docValue
	\param createDir set to true if the intermediate directory should be created
	\return (string, string) the relative and absolute file name of the graphic file
--]]
function OzFilePaths.getWatermarkGraphicPath( catalogId, docValue, optCreateDir )

	WFArguments.check( "string", "table", "?boolean" )

	local documentsPath = KSPathUtils.getStandardFilePath( 'carouselDocuments' )

	local fileName = derefOpt( docValue, 'importSource', 'fileName' )

	local extension = fileName:match( "%.([^%.]+)$" ):lower()

	local saveFileName = KSIdGenerator.uuidInLowercaseHex() .. '.' .. extension

	local relativePath, absolutePath

	relativePath =  KSPathUtils.child('watermarks', docValue._id )

	relativePath = KSPathUtils.child( relativePath, saveFileName )

	absolutePath = KSPathUtils.child( documentsPath, catalogId )

	absolutePath = KSPathUtils.child( absolutePath, relativePath )

	if optCreateDir then

		local parentPath = KSPathUtils.parent( absolutePath )

		WFFileUtils.mkdir( parentPath )

	end

	return relativePath, absolutePath

end

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

if WFPlatformInfo.isAndroid then

--[[!
	\brief convenience function to construct a absolute file path for the external xmp develop document
	based on the docValue.

	\param docValue the docValue
	\return (string) the absolute file path to the external develop settings
--]]

function OzFilePaths.getAbsoluteXmpDevelopPath( docValue, catalogId )

	WFArguments.check( 'table' )

	local basePath = KSPathUtils.getStandardFilePath( 'carouselDocuments' )
	if not basePath then
		return nil
	end

	local xmpDevelopFilePath = KSTableUtils.derefOpt( docValue, '_localOnly', 'files', 'xmp_develop', 'path' )
	if not xmpDevelopFilePath then
		return nil
	end

	return KSPathUtils.child( basePath, xmpDevelopFilePath )

end

end

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

--[[!
	\brief construct a file path for an original based on a originalsFolderDocuments
	path and a capture date in format like this: 2012-10-08T14:15:44
	
	\param originalsFolderDocuments Absolute path to the originalFolderDocuments folder
	\param captureDate Date of the original asset that you're trying to find a home for
]]--

function OzFilePaths.originalsFolderForDate( originalsFolderDocuments, captureDate )

	WFArguments.check( "string", "string" )

	captureDate = captureDate:sub( 1, 10 )

	local folder = KSPathUtils.child( originalsFolderDocuments, captureDate:sub( 1, 4 ) ) -- yyyy
	folder = KSPathUtils.child( folder, captureDate:sub( 1, 7 ) ) -- yyyy-mm
	folder = KSPathUtils.child( folder, captureDate ) -- yyyy-mm-dd
	
	return folder

end

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

--[[!
	\brief construct a relative file from an absolute path and an anchor point
	
	\param absPath Absolute path 
	\param anchor base directory used as an anchor point - for example 'Originals'.
]]--

function OzFilePaths.makeRelativeFrom( absPath, anchor )

	local components = KSStringUtils.split( absPath, WFPlatformInfo.folderSeparator )

	for i = #components, 1, -1 do

		if components[ i ] == anchor then

			components = KSTableUtils.slice( components, i )

			return table.concat( components, WFPlatformInfo.folderSeparator )

		end

	end

	logger:errorf( "could not find anchor %s in absolute path %s", anchor, absPath )

	return nil

end

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

return OzFilePaths
