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

NmbUserModelTest.lua

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

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

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

	-- WF.core.logging
local WFLogger = require 'WFLogger'

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

	-- WF.core.self_test
local WFRxTestCase = require 'WFRxTestCase'
local WFTestModelClient = require 'WFTestModelClient'

	-- WF.core.utils
local KSPathUtils = require 'KSPathUtils'
local WFFileUtils = require 'WFFileUtils'
local WFUnknown = require 'WFUnknown'
local WFPlatformInfo = require 'WFPlatformInfo'

	-- WF.oz_client.managed_catalog
local WFCatUser = require 'WFCatUser'
local WFCatSpec = require 'WFCatSpec'

	-- WF.oz_client.user
local WFOzUserTestSession = require 'WFOzUserTestSession'

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

local KSIdGenerator = require 'KSIdGenerator'

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

local kGlobalDocumentId = '00000000000000000000000000000000'

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

-- @mark NmbUserModelTest

local NmbUserModelTest = {}

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

local coveragePath

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

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

function NmbUserModelTest.setUp( inCoveragePath )

	coveragePath = inCoveragePath

end

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

function NmbUserModelTest.rxTestGetImsAuthUrl_testNightly( rxTest )

	rxTest:setTimeLimit( 60 )

	local factory = WFTestModelClient.makeModelFactory( WFWorkerThread( 'WFModelsTest_Server.lua' ) )
	local model = factory:openModel( 'NmbUserModel.makeUserModel',
									 'https://photos-stage.adobe.io',
									 ':memory:' )
									 
	if coveragePath then
		model:postEvent( 'DEBUG_dumpCoverage', coveragePath )
	end
	
	model:postEvent( "logout" )

	local isLoggedIn = rxTest:observe( model:value():pluck( 'isLoggedIn' ) )
	isLoggedIn:expectDataWithinTime( 5, false )

	if coveragePath then
		model:postEvent( 'DEBUG_dumpCoverage', coveragePath )
	end

	local imsAuthUrlModel = model:subModel( 'getImsAuthUrl' )
	local urlModelValue = rxTest:observe( imsAuthUrlModel:value()
		:map( function( authUrl, baseUrl )
			return authUrl:gsub( 'client_id=[^&]+', 'client_id=blah' ), baseUrl
		end ) )

	urlModelValue:expectDataWithinTime( 10,
		"https://ims-na1-stg1.adobelogin.com/ims/authorize?client_id=blah&locale=en_US&redirect_uri=air-auth%3A%2F%2Fcarousel&scope=openid%2CAdobeID",
		"https://ims-na1-stg1.adobelogin.com/ims" )

end

--------------------------------------------------------------------------------
local function getBaseCatStruct()
	return {
		"Managed Catalog.mcat",
		"Managed Catalog.mcat-wal",
		"Managed Catalog.wfindex",
		"Managed Catalog.wfindex-wal",
		"Managed Catalog.mru",
		"previews.db",
		"settings",
		"cr_settings",
		"cr_defaults",
		"cr_cameraprofiles",
		"people",
		"previews",
		"xmp",
		"originals"
	}
end
--------------------------------------------------------------------------------

local function populateCatalogFolder( catalogBasePath, useBaseStructure, itemsToAdd, itemsToRemove )

	local baseStruct = getBaseCatStruct()
	
	if not WFFileUtils.exists(catalogBasePath) then
		WFFileUtils.mkdir( catalogBasePath )
	end
	
	if useBaseStructure then
		for _, itemName in ipairs ( baseStruct ) do
			local itemPath = KSPathUtils.child( catalogBasePath, itemName)
			if not WFFileUtils.exists( itemPath ) then
				WFFileUtils.mkdir( itemPath )
			end
		end
	end
	
	if itemsToAdd and type(itemsToAdd) == 'table' then
		for _, itemName in ipairs ( itemsToAdd ) do
			local itemPath = KSPathUtils.child( catalogBasePath, itemName)
			if not WFFileUtils.exists( itemPath ) then
				WFFileUtils.mkdir( itemPath )
			end
		end
	end
	
	if itemsToRemove and type(itemsToRemove) == 'table' then
		for _, itemName in ipairs ( itemsToRemove ) do
			local itemPath = KSPathUtils.child( catalogBasePath, itemName)
			if WFFileUtils.exists( itemPath ) then
				WFFileUtils.delete ( itemPath )
			end
		end
	end


end

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

local function testMigrationStatus(localCatBasePath, ozCatBasePath, additionalItems)

	local catItemStatusResults = {
		-- Files -- 
		["Managed Catalog.mcat"] = "",
		["Managed Catalog.mcat-wal"] = "",
		["Managed Catalog.wfindex"] = "",
		["Managed Catalog.wfindex-wal"] = "",
		["Managed Catalog.mru"] = "",
		["previews.db"] = "",
		-- Folders --
		["settings"] = "",
		["cr_settings"] = "",
		["cr_defaults"] = "",
		["cr_cameraprofiles"] = "",
		["people"] = "",
		["previews"] = "",
		["xmp"] = "",
		["originals"] = ""
	}
	
	if additionalItems and type( additionalItems ) == 'table' then 
		for _, itemName in ipairs( additionalItems ) do
			catItemStatusResults[itemName] = ""
		end
	end
	
	-- Go through and check the items
	-- Status can be one of the following:
	-- "NotMoved", "Moved", "Deleted", "BackedUp","Copied"
	
	for itemName, status in pairs( catItemStatusResults ) do
		local localCatItemPath = KSPathUtils.child( localCatBasePath, itemName )
		local ozCatItemPath = KSPathUtils.child( ozCatBasePath, itemName )
		local catBackupItemPath =  KSPathUtils.child( KSPathUtils.child( localCatBasePath, "backup" ), itemName )
		
		if WFFileUtils.exists(  ozCatItemPath ) then
			if WFFileUtils.exists(  localCatItemPath ) then
				catItemStatusResults[itemName] = "Copied"
			else
				catItemStatusResults[itemName] = "Moved"
			end
			
		else
			if WFFileUtils.exists( localCatItemPath ) then
				catItemStatusResults[itemName] = "NotMoved"
			else
				-- Maybe it was backed up
				if WFFileUtils.exists( catBackupItemPath ) then
					catItemStatusResults[itemName] = "BackedUp"
				else
					catItemStatusResults[itemName] = "Deleted"
				end
				
			end

		end
	end

	return catItemStatusResults
end

--------------------------------------------------------------------------------
if WFPlatformInfo.isDesktop then

local NmbUserModel = require 'NmbUserModel'

function NmbUserModelTest.rxTestFreemiumMigrationExistingLocalCatAndNoOzCat( rxTest )

	rxTest:setTimeLimit( 60 )
	local testName = 'localCatalogMigration'
	local basePath = KSPathUtils.child( KSPathUtils.getStandardFilePath( 'temp' ), testName )
	
	local userInfoCachePath = KSPathUtils.child( basePath, 'user' )
	local userId = KSIdGenerator.uuidInLowercaseHex()
	local wfCatUser = WFCatUser( 'https://photos-stage.adobe.io', userId, userInfoCachePath )
	
	-- Create Local Catalog
	local globalDocumentId = kGlobalDocumentId
	local localCatalogBasePath = KSPathUtils.child( basePath, globalDocumentId )
	
	populateCatalogFolder(
		localCatalogBasePath,
		true,
		nil,
		nil
	)
	
	-- Create Oz Catalog
	local catalogId = KSIdGenerator.uuidInLowercaseHex()
	local catalogBasePath = KSPathUtils.child( basePath, catalogId )
	local wfCatalogSpec = WFCatSpec( wfCatUser, catalogId )
	
	-- Run Migration Code
	local didMigrate = NmbUserModel.maybeMigrateFreemiumCatalog ( wfCatalogSpec, basePath )
	
	-- Check if file transfers were successful
	local testResults = testMigrationStatus( localCatalogBasePath, catalogBasePath)
	local expectedTestResults = {
		-- Files -- 
		["Managed Catalog.mcat"] = "Moved",
		["Managed Catalog.mcat-wal"] = "Moved",
		["Managed Catalog.wfindex"] = "Moved",
		["Managed Catalog.wfindex-wal"] = "Moved",
		["Managed Catalog.mru"] = "Moved",
		["previews.db"] = "Deleted",
		-- Folders --
		["settings"] = "Moved",
		["cr_settings"] = "Moved",
		["cr_defaults"] = "Moved",
		["cr_cameraprofiles"] = "Moved",
		["people"] = "Moved",
		["previews"] = "Moved",
		["xmp"] = "Moved",
		["originals"] = "NotMoved"
	}
	
	rxTest:expectEqual( testResults, expectedTestResults)
	rxTest:expectEqual( didMigrate, true )
	rxTest:finally( function()
		WFFileUtils.delete( catalogBasePath )
		WFFileUtils.delete( localCatalogBasePath )
	end )
end

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

function NmbUserModelTest.rxTestFreemiumMigrationExistingLocalCatAndExistingOzCat( rxTest )
	rxTest:setTimeLimit( 60 )
	local testName = 'localCatalogMigration'
	local basePath = KSPathUtils.child( KSPathUtils.getStandardFilePath( 'temp' ), testName )
	
	local userInfoCachePath = KSPathUtils.child( basePath, 'user' )
	local userId = KSIdGenerator.uuidInLowercaseHex()
	local wfCatUser = WFCatUser( 'https://photos-stage.adobe.io', userId, userInfoCachePath )
	
	-- Create Local Catalog
	local globalDocumentId = kGlobalDocumentId
	local localCatalogBasePath = KSPathUtils.child( basePath, globalDocumentId )
	
	populateCatalogFolder(
		localCatalogBasePath,
		true,
		nil,
		nil
	)
	
	-- Create Oz Catalog
	local catalogId = KSIdGenerator.uuidInLowercaseHex()
	local catalogBasePath = KSPathUtils.child( basePath, catalogId )
	local wfCatalogSpec = WFCatSpec( wfCatUser, catalogId )
	
	populateCatalogFolder(
		catalogBasePath,
		true,
		nil,
		nil
	)
	
	-- Run Migration Code
	local didMigrate = NmbUserModel.maybeMigrateFreemiumCatalog ( wfCatalogSpec, basePath )
	
	rxTest:expectEqual( didMigrate, false )

	rxTest:finally( function()
		WFFileUtils.delete( catalogBasePath )
		WFFileUtils.delete( localCatalogBasePath )
	end )
end

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

function NmbUserModelTest.rxTestFreemiumMigrationNoLocalCatAndNoOzCat( rxTest )
	rxTest:setTimeLimit( 60 )
	local testName = 'localCatalogMigration'
	local basePath = KSPathUtils.child( KSPathUtils.getStandardFilePath( 'temp' ), testName )
	
	local userInfoCachePath = KSPathUtils.child( basePath, 'user' )
	local userId = KSIdGenerator.uuidInLowercaseHex()
	local wfCatUser = WFCatUser( 'https://photos-stage.adobe.io', userId, userInfoCachePath )
	
	-- Create Local Catalog
	local globalDocumentId = kGlobalDocumentId
	local localCatalogBasePath = KSPathUtils.child( basePath, globalDocumentId )
	
	-- Create Oz Catalog
	local catalogId = KSIdGenerator.uuidInLowercaseHex()
	local catalogBasePath = KSPathUtils.child( basePath, catalogId )
	local wfCatalogSpec = WFCatSpec( wfCatUser, catalogId )
	
	-- Run Migration Code
	local didMigrate = NmbUserModel.maybeMigrateFreemiumCatalog ( wfCatalogSpec, basePath )
	
	rxTest:expectEqual( didMigrate, false )
	rxTest:finally( function()
		WFFileUtils.delete( catalogBasePath )
		WFFileUtils.delete( localCatalogBasePath )
	end )
end

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

function NmbUserModelTest.rxTestFreemiumMigrationNoLocalCatAndExistingOzCat( rxTest )
	rxTest:setTimeLimit( 60 )
	local testName = 'localCatalogMigration'
	local basePath = KSPathUtils.child( KSPathUtils.getStandardFilePath( 'temp' ), testName )
	
	local userInfoCachePath = KSPathUtils.child( basePath, 'user' )
	local userId = KSIdGenerator.uuidInLowercaseHex()
	local wfCatUser = WFCatUser( 'https://photos-stage.adobe.io', userId, userInfoCachePath )
	
	-- Create Local Catalog
	local globalDocumentId = kGlobalDocumentId
	local localCatalogBasePath = KSPathUtils.child( basePath, globalDocumentId )
	
	-- Create Oz Catalog
	local catalogId = KSIdGenerator.uuidInLowercaseHex()
	local catalogBasePath = KSPathUtils.child( basePath, catalogId )
	local wfCatalogSpec = WFCatSpec( wfCatUser, catalogId )
	
	populateCatalogFolder(
		catalogBasePath,
		true,
		nil,
		nil
	)
	
	-- Run Migration Code
	local didMigrate = NmbUserModel.maybeMigrateFreemiumCatalog ( wfCatalogSpec, basePath )
	
	rxTest:expectEqual( didMigrate, false )
	rxTest:finally( function()
		WFFileUtils.delete( catalogBasePath )
		WFFileUtils.delete( localCatalogBasePath )
	end )

end
--------------------------------------------------------------------------------
function NmbUserModelTest.rxTestFreemiumMigrationExistingEmptyLocalCatAndNoOzCat( rxTest )

	rxTest:setTimeLimit( 60 )
	local testName = 'localCatalogMigration'
	local basePath = KSPathUtils.child( KSPathUtils.getStandardFilePath( 'temp' ), testName )
	
	local userInfoCachePath = KSPathUtils.child( basePath, 'user' )
	local userId = KSIdGenerator.uuidInLowercaseHex()
	local wfCatUser = WFCatUser( 'https://photos-stage.adobe.io', userId, userInfoCachePath )
	
	-- Create Local Catalog
	local globalDocumentId = kGlobalDocumentId
	local localCatalogBasePath = KSPathUtils.child( basePath, globalDocumentId )
	
	populateCatalogFolder(
		localCatalogBasePath,
		false,
		nil,
		nil
	)
	
	-- Create Oz Catalog
	local catalogId = KSIdGenerator.uuidInLowercaseHex()
	local catalogBasePath = KSPathUtils.child( basePath, catalogId )
	local wfCatalogSpec = WFCatSpec( wfCatUser, catalogId )
	
	-- Run Migration Code
	local didMigrate = NmbUserModel.maybeMigrateFreemiumCatalog ( wfCatalogSpec, basePath )
	
	-- Check if file transfers were successful
	local testResults = testMigrationStatus( localCatalogBasePath, catalogBasePath)
	
	-- Expected report "Deleted" when there were no files to begin with
	local expectedTestResults = {
		-- Files -- 
		["Managed Catalog.mcat"] = "Deleted",
		["Managed Catalog.mcat-wal"] = "Deleted",
		["Managed Catalog.wfindex"] = "Deleted",
		["Managed Catalog.wfindex-wal"] = "Deleted",
		["Managed Catalog.mru"] = "Deleted",
		["previews.db"] = "Deleted",
		-- Folders --
		["settings"] = "Deleted",
		["cr_settings"] = "Deleted",
		["cr_defaults"] = "Deleted",
		["cr_cameraprofiles"] = "Deleted",
		["people"] = "Deleted",
		["previews"] = "Deleted",
		["xmp"] = "Deleted",
		["originals"] = "Deleted"
	}
	
	rxTest:expectEqual( testResults, expectedTestResults)
	rxTest:expectEqual( didMigrate, true )
	rxTest:finally( function()
		WFFileUtils.delete( catalogBasePath )
		WFFileUtils.delete( localCatalogBasePath )
	end )
end

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

function NmbUserModelTest.rxTestFreemiumMigrationFileMoveError( rxTest )

	rxTest:setTimeLimit( 60 )
	local testName = 'localCatalogMigration'
	local basePath = KSPathUtils.child( KSPathUtils.getStandardFilePath( 'temp' ), testName )
	
	local userInfoCachePath = KSPathUtils.child( basePath, 'user' )
	local userId = KSIdGenerator.uuidInLowercaseHex()
	local wfCatUser = WFCatUser( 'https://photos-stage.adobe.io', userId, userInfoCachePath )
	
	-- Create Local Catalog
	local globalDocumentId = kGlobalDocumentId
	local localCatalogBasePath = KSPathUtils.child( basePath, globalDocumentId )
	
	populateCatalogFolder(
		localCatalogBasePath,
		true,
		nil,
		nil
	)
	
	-- Create Oz Catalog
	local catalogId = KSIdGenerator.uuidInLowercaseHex()
	local catalogBasePath = KSPathUtils.child( basePath, catalogId )
	local wfCatalogSpec = WFCatSpec( wfCatUser, catalogId )
	
	-- Run Migration Code
	local simulateMoveError = true
	local didMigrate = NmbUserModel.maybeMigrateFreemiumCatalog ( wfCatalogSpec, basePath, simulateMoveError )
	
	-- Check if file transfers were successful
	local testResults = testMigrationStatus( localCatalogBasePath, catalogBasePath)
	
	-- Expected report "Deleted" when there were no files to begin with
	local expectedTestResults = {
		-- Files -- 
		["Managed Catalog.mcat"] = "BackedUp",
		["Managed Catalog.mcat-wal"] = "BackedUp",
		["Managed Catalog.wfindex"] = "BackedUp",
		["Managed Catalog.wfindex-wal"] = "BackedUp",
		["Managed Catalog.mru"] = "BackedUp",
		["previews.db"] = "Deleted", -- This file is still under the deleted flag for maybeMigrateFreemiumCatalog
		-- Folders --
		["settings"] = "BackedUp",
		["cr_settings"] = "BackedUp",
		["cr_defaults"] = "BackedUp",
		["cr_cameraprofiles"] = "BackedUp",
		["people"] = "BackedUp",
		["previews"] = "BackedUp",
		["xmp"] = "BackedUp",
		["originals"] = "NotMoved" -- originals should never be moved. Only thing that should touch this folder is NMBFileMover
	}
	
	rxTest:expectEqual( testResults, expectedTestResults)
	rxTest:expectEqual( didMigrate, true )
	rxTest:finally( function()
		WFFileUtils.delete( catalogBasePath )
		WFFileUtils.delete( localCatalogBasePath )
	end )
end

end

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


if WFPlatformInfo.isMac or WFPlatformInfo.isWindows then
	return WFRxTestCase.wrapSuite( NmbUserModelTest )
else
	return {}
end
