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

WFCatPhotoImportanceTestFactory.lua

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

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

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

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

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

local KSIdGenerator = require 'KSIdGenerator'
local KSDate = require 'KSDate'

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

local createFakeWFCatalog = WFCatMockCatalog.createFakeWFCatalog

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

return function( optSubmodelsByImplementation, maybeExistingTestClass )

	----------------------------------------------------------------------------
	
	local function callFunctionOrSubmodel( rxTest, wfCatalog, fnNamespace, fnName, ... )
	
		return WFModelsUtils.callFunctionOrSubmodel( rxTest, optSubmodelsByImplementation, wfCatalog, fnNamespace, fnName, ... )
					
	end
	
	-----------------------------------------------------------------------------
	
	local WFCatPhotoImportanceTest = maybeExistingTestClass or {}
	
	-----------------------------------------------------------------------------
	
	local function setup( rxTest, assetSubtype )

		rxTest:setTimeLimit( 5 )

		local fakeWfCatalog = createFakeWFCatalog( rxTest )

		local docStore = fakeWfCatalog:docStore()
		
		local docId = KSIdGenerator.uuidInLowercaseHex()

		rxTest:expectSingleValue(

			docStore:setDocValue {
					_id = docId,
					type = 'asset',
					subtype = assetSubtype or 'image',
					importSource = {
						filePath = '/path/',
						originalHeight = 150,
						originalWidth = 100,
					}
				},

			':ignore:' )
			
		return docStore, docId, fakeWfCatalog

	end
--------------------------------------------------------------------------------

	function WFCatPhotoImportanceTest.rxTestFlaggingCatPhotoImportance( rxTest )

		local docStore, docId, wfCatalog = setup( rxTest )

		-- No Flag
		
		rxTest:expectSingleValue( 
			docStore:docValue( docId ):map( function( docValue )
				return callFunctionOrSubmodel(
					rxTest, wfCatalog,
					'WFCatPhotoImportance',
					'isPhotoImportant', docValue )
			end ), false )
		
		-- Reject
		
		rxTest:expectSingleValue(

			docStore:applyOverlay {
					_id = docId,
					reviews = {
						[ 'foo' ] = {
							flag = 'reject'
						},
					},
				},

			':ignore:' )
		
		rxTest:expectSingleValue( 
			docStore:docValue( docId ):map( function( docValue )
				return callFunctionOrSubmodel(
					rxTest, wfCatalog,
					'WFCatPhotoImportance',
					'isPhotoImportant', docValue )
			end ), false )
		
		-- Pick

		rxTest:expectSingleValue(

			docStore:applyOverlay {
					_id = docId,
					reviews = {
						[ 'foo' ] = {
							flag = 'pick'
						},
					},
				},

			':ignore:' )

		rxTest:expectSingleValue( 
			docStore:docValue( docId ):map( function( docValue )
				return callFunctionOrSubmodel(
					rxTest, wfCatalog,
					'WFCatPhotoImportance',
					'isPhotoImportant', docValue )
			end ), true )

	end

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

	function WFCatPhotoImportanceTest.rxTestRatingsCatPhotoImportance( rxTest )

		local docStore, docId, wfCatalog = setup( rxTest )

		-- No Ratings
		
		rxTest:expectSingleValue( 
			docStore:docValue( docId ):map( function( docValue )
				return callFunctionOrSubmodel(
					rxTest, wfCatalog,
					'WFCatPhotoImportance',
					'isPhotoImportant', docValue )
			end ), false )
		
		-- 2 Star
		
		rxTest:expectSingleValue(

			docStore:applyOverlay {
					_id = docId,
					ratings = {
						[ 'foo' ] = {
							rating = 2
						},
					},
				},

			':ignore:' )
		
		rxTest:expectSingleValue( 
			docStore:docValue( docId ):map( function( docValue )
				return callFunctionOrSubmodel(
					rxTest, wfCatalog,
					'WFCatPhotoImportance',
					'isPhotoImportant', docValue )
			end ), false )
		
		-- 5 Star

		rxTest:expectSingleValue(

			docStore:applyOverlay {
					_id = docId,
					ratings = {
						[ 'foo' ] = {
							rating = 5
						},
					},
				},

			':ignore:' )

		rxTest:expectSingleValue( 
			docStore:docValue( docId ):map( function( docValue )
				return callFunctionOrSubmodel(
					rxTest, wfCatalog,
					'WFCatPhotoImportance',
					'isPhotoImportant', docValue )
			end ), true )

	end

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

	function WFCatPhotoImportanceTest.rxTestModifiedDate( rxTest )

		local docStore, docId, wfCatalog = setup( rxTest )

		-- No Modified Date
		
		rxTest:expectSingleValue( 
			docStore:docValue( docId ):map( function( docValue )
				return callFunctionOrSubmodel(
					rxTest, wfCatalog,
					'WFCatPhotoImportance',
					'isPhotoImportant', docValue )
			end ), false )
		
		-- Not Recently Modified
		
		rxTest:expectSingleValue(

			docStore:applyOverlay {
					_id = docId,
					_serverProvidedMetadata = {
						updated = "2014-06-01T14:42:10-04:00"
					},
				},

			':ignore:' )
		
		rxTest:expectSingleValue( 
			docStore:docValue( docId ):map( function( docValue )
				return callFunctionOrSubmodel(
					rxTest, wfCatalog,
					'WFCatPhotoImportance',
					'isPhotoImportant', docValue )
			end ), false )
		
		-- Recently Modified

		rxTest:expectSingleValue(

			docStore:applyOverlay {
					_id = docId,
					_serverProvidedMetadata = {
						updated = KSDate.timeInIso8601Format()
					},
				},

			':ignore:' )

		rxTest:expectSingleValue( 
			docStore:docValue( docId ):map( function( docValue )
				return callFunctionOrSubmodel(
					rxTest, wfCatalog,
					'WFCatPhotoImportance',
					'isPhotoImportant', docValue )
			end ), true )

	end

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

	function WFCatPhotoImportanceTest.rxTestImportedDate( rxTest )

		local docStore, docId, wfCatalog = setup( rxTest )

		-- No Imported Date
		
		rxTest:expectSingleValue( 
			docStore:docValue( docId ):map( function( docValue )
				return callFunctionOrSubmodel(
					rxTest, wfCatalog,
					'WFCatPhotoImportance',
					'isPhotoImportant', docValue )
			end ), false )
		
		-- Not Recently Imported
		
		rxTest:expectSingleValue(

			docStore:applyOverlay {
					_id = docId,
					importSource = {
						importTimestamp = "2014-06-01T14:42:10-04:00"
					},
				},

			':ignore:' )
		
		rxTest:expectSingleValue( 
			docStore:docValue( docId ):map( function( docValue )
				return callFunctionOrSubmodel(
					rxTest, wfCatalog,
					'WFCatPhotoImportance',
					'isPhotoImportant', docValue )
			end ), false )
		
		-- Recently Imported

		rxTest:expectSingleValue(

			docStore:applyOverlay {
					_id = docId,
					importSource = {
						importTimestamp = KSDate.timeInIso8601Format()
					},
				},

			':ignore:' )

		rxTest:expectSingleValue( 
			docStore:docValue( docId ):map( function( docValue )
				return callFunctionOrSubmodel(
					rxTest, wfCatalog,
					'WFCatPhotoImportance',
					'isPhotoImportant', docValue )
			end ), true )

	end

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

	function WFCatPhotoImportanceTest.rxTestInAppContributeAssetPriority( rxTest )
		
		local docStore, _, wfCatalog = setup( rxTest )
		
		local spaceId = KSIdGenerator.uuidInLowercaseHex()
		local spaceDocId = KSIdGenerator.uuidInLowercaseHex()
		
		rxTest:expectSingleValue( 
			docStore:setDocValue {
					_id = spaceDocId,
					_spaceId = spaceId,
					type = 'asset',
					subtype = 'image',
					importSource = {
						filePath = '/path/',
						originalHeight = 150,
						originalWidth = 100,
					}
				},

			':ignore:' )
		
		rxTest:expectSingleValue(
			docStore:docValue( spaceDocId ):map( function( docValue )
				return callFunctionOrSubmodel(
					rxTest, wfCatalog,
					'WFCatPhotoImportance',
					'getPriorityForUpload', docValue )
			end ), -10 )
			
		
		-- Reject
		rxTest:expectSingleValue(

			docStore:applyOverlay {
					_id = spaceDocId,
					reviews = {
						[ 'foo' ] = {
							flag = 'reject'
						},
					},
				},

			':ignore:' )
		
		rxTest:expectSingleValue( 
			docStore:docValue( spaceDocId ):map( function( docValue )
				return callFunctionOrSubmodel(
					rxTest, wfCatalog,
					'WFCatPhotoImportance',
					'getPriorityForUpload', docValue )
			end ), -11 )
		
		-- Pick

		rxTest:expectSingleValue(

			docStore:applyOverlay {
					_id = spaceDocId,
					reviews = {
						[ 'foo' ] = {
							flag = 'pick'
						},
					},
				},

			':ignore:' )

		rxTest:expectSingleValue( 
			docStore:docValue( spaceDocId ):map( function( docValue )
				return callFunctionOrSubmodel(
					rxTest, wfCatalog,
					'WFCatPhotoImportance',
					'getPriorityForUpload', docValue )
			end ), -9 )

		-- 2 Star
		
		rxTest:expectSingleValue(

			docStore:applyOverlay {
					_id = spaceDocId,
					ratings = {
						[ 'foo' ] = {
							rating = 2
						},
					},
				},

			':ignore:' )
		
		rxTest:expectSingleValue( 
			docStore:docValue( spaceDocId ):map( function( docValue )
				return callFunctionOrSubmodel(
					rxTest, wfCatalog,
					'WFCatPhotoImportance',
					'getPriorityForUpload', docValue )
			end ), -8.6 )
		
		-- 5 Star

		rxTest:expectSingleValue(

			docStore:applyOverlay {
					_id = spaceDocId,
					ratings = {
						[ 'foo' ] = {
							rating = 5
						},
					},
				},

			':ignore:' )

		rxTest:expectSingleValue( 
			docStore:docValue( spaceDocId ):map( function( docValue )
				return callFunctionOrSubmodel(
					rxTest, wfCatalog,
					'WFCatPhotoImportance',
					'getPriorityForUpload', docValue )
			end ), -8 )
	end


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

	function WFCatPhotoImportanceTest.rxTestGetPriorityForUpload( rxTest )

		local docStore, docId, wfCatalog = setup( rxTest )

		-- No Flags or Ratings
		
		rxTest:expectSingleValue( 
			docStore:docValue( docId ):map( function( docValue )
				return callFunctionOrSubmodel(
					rxTest, wfCatalog,
					'WFCatPhotoImportance',
					'getPriorityForUpload', docValue )
			end ), 0 )
		
		-- Reject
		
		rxTest:expectSingleValue(

			docStore:applyOverlay {
					_id = docId,
					reviews = {
						[ 'foo' ] = {
							flag = 'reject'
						},
					},
				},

			':ignore:' )
		
		rxTest:expectSingleValue( 
			docStore:docValue( docId ):map( function( docValue )
				return callFunctionOrSubmodel(
					rxTest, wfCatalog,
					'WFCatPhotoImportance',
					'getPriorityForUpload', docValue )
			end ), -1 )
		
		-- Pick

		rxTest:expectSingleValue(

			docStore:applyOverlay {
					_id = docId,
					reviews = {
						[ 'foo' ] = {
							flag = 'pick'
						},
					},
				},

			':ignore:' )

		rxTest:expectSingleValue( 
			docStore:docValue( docId ):map( function( docValue )
				return callFunctionOrSubmodel(
					rxTest, wfCatalog,
					'WFCatPhotoImportance',
					'getPriorityForUpload', docValue )
			end ), 1 )

		-- 2 Star
		
		rxTest:expectSingleValue(

			docStore:applyOverlay {
					_id = docId,
					ratings = {
						[ 'foo' ] = {
							rating = 2
						},
					},
				},

			':ignore:' )
		
		rxTest:expectSingleValue( 
			docStore:docValue( docId ):map( function( docValue )
				return callFunctionOrSubmodel(
					rxTest, wfCatalog,
					'WFCatPhotoImportance',
					'getPriorityForUpload', docValue )
			end ), 1.4 )
		
		-- 5 Star

		rxTest:expectSingleValue(

			docStore:applyOverlay {
					_id = docId,
					ratings = {
						[ 'foo' ] = {
							rating = 5
						},
					},
				},

			':ignore:' )

		rxTest:expectSingleValue( 
			docStore:docValue( docId ):map( function( docValue )
				return callFunctionOrSubmodel(
					rxTest, wfCatalog,
					'WFCatPhotoImportance',
					'getPriorityForUpload', docValue )
			end ), 2 )

		-- un-picked, un-rated trash asset

		local trashDocId = KSIdGenerator.uuidInLowercaseHex()

		rxTest:expectSingleValue(

			docStore:setDocValue {
					_id = trashDocId,
					type = 'asset',
					subtype = 'deleted_image',
					importSource = {
						filePath = '/path/',
						originalHeight = 150,
						originalWidth = 100,
					}
				},

			':ignore:' )

		rxTest:expectSingleValue(
			docStore:docValue( trashDocId ):map( function( docValue )
				return callFunctionOrSubmodel(
					rxTest, wfCatalog,
					'WFCatPhotoImportance',
					'getPriorityForUpload', docValue )
			end ), -4 )

		-- Rejected, un-rated trash asset

		rxTest:expectSingleValue(

			docStore:applyOverlay {
					_id = trashDocId,
					reviews = {
						[ 'foo' ] = {
							flag = 'reject'
						},
					},
				},

			':ignore:' )

		rxTest:expectSingleValue(
			docStore:docValue( trashDocId ):map( function( docValue )
				return callFunctionOrSubmodel(
					rxTest, wfCatalog,
					'WFCatPhotoImportance',
					'getPriorityForUpload', docValue )
			end ), -5 )

		-- Picked, highest rated trash asset

		rxTest:expectSingleValue(

			docStore:applyOverlay {
					_id = trashDocId,
					ratings = {
						[ 'foo' ] = {
							rating = 5
						},
					},
					reviews = {
						[ 'foo' ] = {
							flag = 'pick'
						},
					},
				},

			':ignore:' )

		-- Note this is less than a rejected un-rated asset

		rxTest:expectSingleValue(
			docStore:docValue( trashDocId ):map( function( docValue )
				return callFunctionOrSubmodel(
					rxTest, wfCatalog,
					'WFCatPhotoImportance',
					'getPriorityForUpload', docValue )
			end ), -2 )
		

	end

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

	function WFCatPhotoImportanceTest.rxTestUploadPriorityModifiers( rxTest )

		local docStore, docId, wfCatalog = setup( rxTest )

		-- No Modifiers
		
		rxTest:expectSingleValue( 
			docStore:docValue( docId ):map( function( docValue )
				return callFunctionOrSubmodel(
					rxTest, wfCatalog,
					'WFCatPhotoImportance',
					'getUploadPriorityModifier', docValue )
			end ), nil )
		
		rxTest:expectSingleValue( 
			docStore:docValue( docId ):map( function( docValue )
				return callFunctionOrSubmodel(
					rxTest, wfCatalog,
					'WFCatPhotoImportance',
					'getPriorityForUpload', docValue )
			end ), 0 )
		
		-- Important Modifier
		
		rxTest:waitFor( callFunctionOrSubmodel(
					rxTest, wfCatalog,
					'WFCatPhotoImportance',
					'increaseUploadPriorityForAsset', wfCatalog, docId ) )
		
		rxTest:expectSingleValue( 
			docStore:docValue( docId ):map( function( docValue )
				return callFunctionOrSubmodel(
					rxTest, wfCatalog,
					'WFCatPhotoImportance',
					'getUploadPriorityModifier', docValue )
			end ), 'IMPORTANT' )
		
		rxTest:expectSingleValue( 
			docStore:docValue( docId ):map( function( docValue )
				return callFunctionOrSubmodel(
					rxTest, wfCatalog,
					'WFCatPhotoImportance',
					'getPriorityForUpload', docValue )
			end ), 100 )
		
		-- Critical Modifier
		
		rxTest:waitFor( callFunctionOrSubmodel(
					rxTest, wfCatalog,
					'WFCatPhotoImportance',
					'increaseUploadPriorityForAsset', wfCatalog, docId, true ) )
		
		rxTest:expectSingleValue( 
			docStore:docValue( docId ):map( function( docValue )
				return callFunctionOrSubmodel(
					rxTest, wfCatalog,
					'WFCatPhotoImportance',
					'getUploadPriorityModifier', docValue )
			end ), 'CRITICAL' )
		
		rxTest:expectSingleValue( 
			docStore:docValue( docId ):map( function( docValue )
				return callFunctionOrSubmodel(
					rxTest, wfCatalog,
					'WFCatPhotoImportance',
					'getPriorityForUpload', docValue )
			end ), 1000 )
		
		-- Remove Modifier

		rxTest:waitFor( callFunctionOrSubmodel(
					rxTest, wfCatalog,
					'WFCatPhotoImportance',
					'removeUploadPriorityModifier', wfCatalog, docId ) )

		rxTest:expectSingleValue( 
			docStore:docValue( docId ):map( function( docValue )
				return callFunctionOrSubmodel(
					rxTest, wfCatalog,
					'WFCatPhotoImportance',
					'getUploadPriorityModifier', docValue )
			end ), nil )
		
		rxTest:expectSingleValue( 
			docStore:docValue( docId ):map( function( docValue )
				return callFunctionOrSubmodel(
					rxTest, wfCatalog,
					'WFCatPhotoImportance',
					'getPriorityForUpload', docValue )
			end ), 0 )

	end

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

	return maybeExistingTestClass and WFCatPhotoImportanceTest
			or WFRxTestCase.wrapSuite( WFCatPhotoImportanceTest )

end
