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

WFCatUserTest.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.os
local KSPathUtils = require 'KSPathUtils'
local KSIdGenerator = require "KSIdGenerator"
local WFFileUtils = require 'WFFileUtils'

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

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

	-- WF.sqlite.doc_store
local WFRxDocStore = require 'WFRxDocStore'

	-- WF.oz_client.managed_catalog
local WFCatTestSession = require 'WFCatTestSession'

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

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

local check = assert( WFArguments.check )

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

local WFCatUserTest = {}

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

local kUser1 = string.rep( '1', 32 )
local kUser2 = string.rep( '2', 32 )
local kUser3 = string.rep( '3', 32 )

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

function WFCatUserTest.rxTestBasic( rxTest )

	local user1 = WFCatUser( 'app://server-base', kUser1, ':memory:' )

	rxTest:expectEqual( 'app://server-base', user1:serverBaseUrl() )
	rxTest:expectEqual( kUser1, user1:userId() )
	rxTest:expectEqual( ':memory:' .. kUser1, user1:userInfoCachePath() )

	local userInfoCache = user1:userInfoCache()

	rxTest:expectEqual( true, WFRxDocStore:isClassOf( userInfoCache ) )
	rxTest:expectEqual( 'string', type( tostring( user1 ) ) )

	-- Non-memory one for boosting coverage in WFCatUser:userInfoCachePath.
	local tempSubFolder = KSPathUtils.child( KSPathUtils.getStandardFilePath( 'temp' ),
		KSIdGenerator.uuidInLowercaseHex() )

	print( tempSubFolder )

	WFFileUtils.mkdir( tempSubFolder )
	
	local user2 = WFCatUser( 'app://server-base', kUser2, tempSubFolder )

	rxTest:expectEqual( true, not not user2:userInfoCachePath() )
	
	rxTest:expectEqual( tempSubFolder, user2:userInfoCacheFolder() )
	
	local user3 = WFCatUser( 'app://server-base', kUser3, ':memory:' )

	rxTest:expectEqual( kUser3, user3:userId() )
	
	rxTest:finally( function()
		user1:close()
		user2:close()
		user3:close()
		pcall( WFFileUtils.delete, tempSubFolder )
	end )
	
end

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

function WFCatUserTest.rxTestInitValidatesArguments( rxTest )

	rxTest:expectError( function()

		return WFCatUser( 'app:', 'invalid' )

	end )

end

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

function WFCatUserTest.rxTestDynamicEndpoint( rxTest )

	rxTest:setTimeLimit( 50 )
	
	local endpointIndexDocId = 'Oz-EndpointIndexDocument'
	
	local user = WFCatUser( 'app://server-base', kUser1, ':memory:' )
	
	local oauthSessionMock = Rx.Class( 'WFOAuth2Session', {
	
		get = function( self, url )
			return Rx.Observable.just( url )
		end,
		
		put = function( self, url )
			return Rx.Observable.just( url )
		end,
		
	} )()
	
	
	rawset( user._sharedInstance, '_oAuth2Session', oauthSessionMock )
	
	rxTest:expectEqual( 'app://server-base', user:serverBaseUrl() )
	
	rxTest:expectSingleValue( user:get( '/catalogs' ), 'app://server-base/catalogs' )
	
	rxTest:expectOnlyCompleted( user:userInfoCache():applyOverlayLocalDocValue( {
		_id = endpointIndexDocId,
		base = 'app://server-base-v2',
	} ) )
	
	rxTest:expectSingleValue( user:get( '/catalogs' ), 'app://server-base-v2/catalogs' )
	
	rxTest:expectEqual( 'app://server-base-v2', user:serverBaseUrl() )
	
	rxTest:expectOnlyCompleted( user:userInfoCache():applyOverlayLocalDocValue( {
		_id = endpointIndexDocId,
		base = 'app://server-base-v2',
		links = {
			[ '/rels/storage' ] = {
				base = 'app://binary-base',
			}
		}
	} ) )
	
	rxTest:expectSingleValue( user:get( '/catalogs' ), 'app://server-base-v2/catalogs' )
	
	rxTest:expectSingleValue( user:getBinary( '/master' ), 'app://binary-base/master' )
	
	rxTest:expectOnlyCompleted( user:userInfoCache():applyOverlayLocalDocValue( {
		_id = endpointIndexDocId,
		base = 'app://server-base-v2',
		links = {
			[ '/rels/storage' ] = {
				base = 'app://binary-base-v2',
			}
		}
	} ) )
	
	rxTest:expectSingleValue( user:getBinary( '/master' ), 'app://binary-base-v2/master' )
	
	rxTest:expectSingleValue( user:put( '/catalogs' ), 'app://server-base-v2/catalogs' )
	
	rxTest:expectSingleValue( user:getBinary( '/master' ), 'app://binary-base-v2/master' )
	
	rxTest:expectSingleValue( user:putBinary( '/master' ), 'app://binary-base-v2/master' )
	
end

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

function WFCatUserTest.rxTestUpdateCommPrefOnOz_testNightly( rxTest )

	rxTest:setTimeLimit( 30 )

	local catalogTestSession = WFCatTestSession( rxTest )

	local wfCatUser

	rxTest:expectSingleValue(

		catalogTestSession:wfCatUser()
			:map( function( ozUser )
				check( 'WFCatUser' )
				wfCatUser = ozUser
				return true
			end ), 

		true )

	-- Set the language preference to spanish

	local locale = 'es-ES'

	rxTest:expectSingleValue(

		wfCatUser:updateCommunicationPreference( locale ), 

		locale )

	-- Verify that the communication preference was updated correctly.

	rxTest:expectSingleValue( 

		wfCatUser:getAccountDocFromOz()
			:map( function( userAccountDoc )
				local communicationPreference = KSTableUtils.derefOpt( userAccountDoc, 
													'payload', 
													'universal', 
													'communication_preference' )
				return communicationPreference
			end ), 

		locale )

	-- Try updating the locale now that it is already set

	local newLocale = 'en-US'

	rxTest:expectSingleValue(

		wfCatUser:updateCommunicationPreference( newLocale ), 

		nil )

	-- Verify that the communication preference was not updated.

	rxTest:expectSingleValue( 

		wfCatUser:getAccountDocFromOz()
			:map( function( userAccountDoc )
				local communicationPreference = KSTableUtils.derefOpt( userAccountDoc, 
													'payload', 
													'universal', 
													'communication_preference' )
				return communicationPreference
			end ), 

		locale )

end

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

function WFCatUserTest.rxTestUpdateCommPrefOnOzNoLocaleArg_testNightly( rxTest )

	rxTest:setTimeLimit( 30 )

	local catalogTestSession = WFCatTestSession( rxTest )

	local wfCatUser

	rxTest:expectSingleValue(

		catalogTestSession:wfCatUser()
			:map( function( ozUser )
				check( 'WFCatUser' )
				wfCatUser = ozUser
				return true
			end ), 

		true )

	-- Verify that the communication preference is not set on Oz

	rxTest:expectSingleValue( 

		wfCatUser:getAccountDocFromOz()
			:map( function( userAccountDoc )
				local communicationPreference = KSTableUtils.derefOpt( userAccountDoc, 
													'payload', 
													'universal', 
													'communication_preference' )
				return communicationPreference
			end ), 

		nil )

	-- Do not explicitly pass locale as an argument
	-- Expected to derive from device settings and update on Oz

	local locale

	rxTest:expectSingleValue(

		wfCatUser:updateCommunicationPreference() 
			:map( function( optLocale )
				locale = optLocale
				return true
			end ), 

		true )

	-- Verify that the communication preference updated with locale

	rxTest:expectSingleValue( 

		wfCatUser:getAccountDocFromOz()
			:map( function( userAccountDoc )
				local communicationPreference = KSTableUtils.derefOpt( userAccountDoc, 
													'payload', 
													'universal', 
													'communication_preference' )
				return communicationPreference
			end ),

		locale )

end

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

-- NOTE: WFCatUser:createCatalog is tested via 
-- WFCatTestSessionTest.rxTestOzUserConstruction_testNightly

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

return WFRxTestCase.wrapSuite( WFCatUserTest )
