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

WFCatMockCatalog.lua

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

ADOBE CONFIDENTIAL
------------------
Copyright 2015 Adobe Systems Incorporated
All Rights Reserved.

NOTICE: All information contained herein is, and remains 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 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 Systems Incorporated.

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

	-- RxLua
local Rx = require 'Rx'

	-- WF.core.self_test
local WFTestFileUtils = require 'WFTestFileUtils'

	-- WF.oz_client.sync_agent
local OzCatalogUrls = require 'OzCatalogUrls'

	-- WF.core.utils
local KSPathUtils = require 'KSPathUtils'
local WFCatPixelPathGenerator = require 'WFCatPixelPathGenerator'
local WFCloseSupport = require 'WFCloseSupport'
local WFFileUtils = require 'WFFileUtils'
local KSIdGenerator = require 'KSIdGenerator'
local WFObjectProxy = require 'WFObjectProxy'

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

local WFCatMockCatalog = {}

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

local WFCatFileSpecMock = {
	_basePath = false,
	_docStorePath = false,
	WFCloseSupport.addCloseSupportMethods,
}

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

function WFCatFileSpecMock:__init( basePath, docStorePath )
	self._basePath = basePath
	self._docStorePath = docStorePath
	WFFileUtils.mkdir( basePath )
end

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

function WFCatFileSpecMock:pixelsPath()
	local path =  KSPathUtils.child( self._basePath, 'renditionsPath' )
	WFFileUtils.mkdir( path )
	return path
end

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

function WFCatFileSpecMock:catalogPath()
	local path = KSPathUtils.child( self._basePath, 'catalogPath' )
	WFFileUtils.mkdir( path )
	return path
end

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

function WFCatFileSpecMock:docStorePath()
	return self._docStorePath or ':memory:'
end

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

function WFCatFileSpecMock:deletionBacklogPath()
	return ':memory:'
end

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

function WFCatFileSpecMock:rootPath()
	return self._basePath
end

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

function WFCatFileSpecMock:catalogPathInfo()

	local volumeGuid = WFFileUtils.getVolumeGuidForPath( self._basePath )
	local relativePath = WFFileUtils.removeVolumeFromPath( self._basePath )

	return {
		volumeGuid = volumeGuid,
		relativePath = relativePath,
	}

end

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

function WFCatFileSpecMock:tempFolderPathForVolume()

	local tempFolder = KSPathUtils.getStandardFilePath( "temp" )
	pcall( WFFileUtils.mkdir, tempFolder )

	return tempFolder

end

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

function WFCatFileSpecMock:originalsPathInfo()

	local volumeGuid = WFFileUtils.getVolumeGuidForPath( self._basePath )
	local relativePath = WFFileUtils.removeVolumeFromPath( self._basePath )

	return {
		volumeGuid = volumeGuid,
		relativePath = relativePath,
	}

end

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

function WFCatFileSpecMock:proxiesPathInfo()

	local volumeGuid = WFFileUtils.getVolumeGuidForPath( self._basePath )
	local relativePath = WFFileUtils.removeVolumeFromPath( self._basePath )

	return {
		volumeGuid = volumeGuid,
		relativePath = relativePath,
	}

end

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

function WFCatFileSpecMock:pathForOriginal( fileName, captureDate )

	return WFCatPixelPathGenerator.pathForOriginal( self._basePath, fileName, captureDate )

end

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

function WFCatFileSpecMock:pathForProxy( assetId, proxyType )

	return WFCatPixelPathGenerator.pathForProxyTypeAndUuid( self._basePath, proxyType, assetId )

end

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

function WFCatFileSpecMock:pathForXmpSidecar( assetId )

	return WFCatPixelPathGenerator.pathForXmpSidecar( self._basePath, assetId )

end

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

function WFCatFileSpecMock:folderForSettingsXmp()

	return WFCatPixelPathGenerator.folderForSettingsXmp( self:pixelsPath() )

end

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

function WFCatFileSpecMock:pathForSettingsXmp( sha256 )

	return WFCatPixelPathGenerator.pathForSettingsXmp( self:pixelsPath(), sha256 )

end

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

function WFCatFileSpecMock:pathForStyle( assetId )

	return WFCatPixelPathGenerator.pathForStyle( self:pixelsPath(), assetId )

end

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

function WFCatFileSpecMock:maybeStylePath( path )

	return WFCatPixelPathGenerator( self:pixelsPath(), path )

end

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

function WFCatFileSpecMock:pathForPreviewDigestAndLongEdge( uuid, digest, longEdge, optCreateDirectory )

	return WFCatPixelPathGenerator.pathForPreviewDigestAndLongEdge( self._basePath,
		uuid, digest, longEdge, optCreateDirectory )

end

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

function WFCatFileSpecMock:close()
	WFFileUtils.deleteDirectory( self._basePath )
end

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

WFCatFileSpecMock = Rx.Class( 'WFCatFileSpec', WFCatFileSpecMock )

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

local function getUniqueBasePath( rxTest )

	-- have seen windows test fail with failures when test names are too long,
	-- unable to write files when path string is too long.
	local shortTestName = rxTest:testName()
	if string.len(shortTestName) > 50 then
		shortTestName = string.sub(shortTestName, 1, 24) .. '_' .. string.sub(shortTestName, -25, -1)
	end

	return KSPathUtils.child(
				KSPathUtils.child(
					KSPathUtils.getStandardFilePath( 'temp' ),
					KSIdGenerator.uuidInLowercaseHex() ),
				shortTestName )

end

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

local fakeWFCatalog = Rx.Class 'WFCatalog' {
	_docStore = false,
	_indexStore = false,
	_ozCatalogId = false,
	_ozUserId = false,
	_deletionBacklog = false,
	_searchSchema = false,
	_fileSpec = false,
	_catSpec = false,
	_volumeAgents = false,
	_albumsCache = false,
	_userInfoCachePath = false,
	_userInfoCache = false,

	WFCloseSupport.addCloseSupportMethods,

	__init = function( self, rxTest, ozUserId, optDocStorePath, optRequestResponsePairs, optIndexDefinitions, optArgs )

		local WFRxDocStore = require 'WFRxDocStore'
		local WFRxIndexStore = require 'WFRxIndexStore'
		local NmbDeletionBacklog = require 'NmbDeletionBacklog'

		local docStorePath = optDocStorePath

		if not docStorePath then
            
			docStorePath = ':memory:' .. tostring( KSIdGenerator.localCounter() )
			
		end
		
		local basePath = getUniqueBasePath( rxTest )
		local fileSpec = WFCatFileSpecMock( basePath, docStorePath )
		
		optArgs = optArgs or {}
		local enablePlatformIndexStore = optArgs.enablePlatformIndexStore
		optArgs.enablePlatformIndexStore = nil

		local docStore = WFRxDocStore( docStorePath )
		local indexStore = WFRxIndexStore( docStore, optIndexDefinitions or 'WFCatIndexDefinitions.lua', nil, enablePlatformIndexStore )

		optArgs.writeInterval = optArgs.writeInterval or 0.1
		optArgs.doNotInitialize = true
		optArgs.isDebugMode = true

		local deletionBacklog = NmbDeletionBacklog( docStorePath, fileSpec:deletionBacklogPath(), optArgs )

		local searchSchema = require 'WFCatSearchSchema'()
		require 'WFCatSearchHandler'.addSearchToSearchSchema( searchSchema )
		require 'WFCatIdleDownloader'.addSearchToSearchSchema( searchSchema )

		local catalogId = KSIdGenerator.uuidInLowercaseHex()
		
		self._ozCatalogId = catalogId
		self._ozUserId = ozUserId
		self._searchSchema = searchSchema
		self._volumeAgents = {}

		self._catSpec = require 'WFCatSpecMock'( catalogId, ozUserId, rxTest, optRequestResponsePairs or {} )

		WFTestFileUtils.addTestFolder( basePath )

		self:setOwned {
			_docStore = docStore,
			_indexStore = indexStore,
			_deletionBacklog = deletionBacklog,
			_fileSpec = fileSpec,
		}

	end,
	docStore = function( self )
		return self._docStore
	end,
	indexStore = function( self )
		return self._indexStore
	end,
	deletionBacklog = function( self )
		return self._deletionBacklog
	end,
	ozUserId = function( self )
		return self._ozUserId
	end,
	ozUser = function( self )
		return {
			purgeAssetsAfterValue = function() return Rx.Observable.just( 60*24*60*60 ) end,
			sharingPolicies = function() 
				return Rx.Observable.just( {
					invitationSharingDisallowed = false,
					invitationSharingAllowDomains = false,
					publicSharingDisallowed = true,
					requestAccessSharingDisallowed = false,
					anyoneCanUploadDisallowed = false,
					feedbackDisallowed = false,
					communityPostingDisallowed = false
				} )
			end,
			mapPartialUrlToCompleteUrl = function( _, url )
				return string.format( "https://photos.adobe.io/v2%s", url )
			end,
			userId = function()
				return self._ozUserId
			end,
			serverBaseUrl = function()
				return OzCatalogUrls.baseServerUrl
			end,
			userInfoCacheFolder = function()
				return ':memory:'
			end,
			userInfoCache = function()
				if not self._userInfoCache
					or WFCloseSupport.hasBeenOrWillBeClosed( self._userInfoCache )
				then
					local userInfoCachePath = ':memory:' .. tostring( KSIdGenerator.localCounter() )
					self:setOwned {
						_userInfoCache = require 'WFRxDocStore'( userInfoCachePath )
					}
				end
				return self._userInfoCache
			end,
		}
	end,
	ozCatalogId = function( self )
		return self._ozCatalogId
	end,
	searchSchema = function( self )
		return self._searchSchema
	end,
	fileSpec = function( self )
		return self._fileSpec
	end,
	ozCatalogSpec = function( self )
		return self._catSpec
	end,
	relayObject = function( self )
		return self
	end,
	getAllVolumeAgents = function( self )
		return self._volumeAgents
	end,
	getDeletionBacklog = function( self )
		return self._deletionBacklog
	end,
	addVolumeAgent = function( self, volumeAgent )
		self._volumeAgents[ volumeAgent:getVolumeGuid() ] = volumeAgent
	end,
	albumsCache = function( self )
		if not self._albumsCache then
			local albumsCache = require 'NmbAlbumsCache'( self )
			self:setOwned {
				_albumsCache = albumsCache
			}
		end
		return self._albumsCache
	end,
}

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

function WFCatMockCatalog.createFakeWFCatalog( rxTest, optDocStorePath, optRequestResponsePairs, optArgs )

	optArgs = optArgs or {}

	local fakeWFCatalogClass = WFObjectProxy( 'WFCatalog', fakeWFCatalog, nil, true )

	local optIndexDefinitions = optArgs.indexDefinitions

	local fakeOzUserId = KSIdGenerator.uuidInLowercaseHex()
	
	local result = fakeWFCatalogClass( rxTest, fakeOzUserId, optDocStorePath, optRequestResponsePairs, optIndexDefinitions, optArgs )

	if not optArgs.keepOpenAfterTestFinishes then

		rxTest:finally( function()
			result:close()
		end )

	end

	return result

end

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

function WFCatMockCatalog.createWFCatalogForTestWithSpec( rxTest, wfCatalogSpec, optCatalogClassType, optIndexSpecScript, optDocStorePath )

	local basePath = getUniqueBasePath( rxTest )

	local optArgs = {
		docStorePath = ':memory:',
		deletionBacklogPath = ':memory:',
		indexSpecScript = optIndexSpecScript,
	}

	local catalog = require ( optCatalogClassType or 'WFCatalog' )( wfCatalogSpec, basePath, optArgs )

	rxTest:finally( function()
		catalog:close() -- closing the catalog will delete the basePath
	end )

	return catalog
end

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

function WFCatMockCatalog.createWFCatalogForProfiles( rxTest, wfCatalogSpec, indexSpecScript, optCatalogClassType )

	local basePath = getUniqueBasePath( rxTest )

	local optArgs = {
		docStorePath = ':memory:',
		deletionBacklogPath = ':memory:',
		indexSpecScript = indexSpecScript,
	}

	local catalog = require ( optCatalogClassType or 'WFCatalog' )( wfCatalogSpec, basePath, optArgs )

	rxTest:finally( function()
		catalog:close() -- closing the catalog will delete the basePath
	end )

	return catalog
end

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

return WFCatMockCatalog
