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

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

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

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

	-- WF.core.rxlua
--local WFRxRunUntilDone = require 'WFRxRunUntilDone'

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

	-- WF.core.utils
local WFCloseSupport = require 'WFCloseSupport'

	-- WF.oz_client.managed_catalog.search
local WFCatSearchQuery = require 'WFCatSearchQuery'
local WFCatSearchSchema = require 'WFCatSearchSchema'

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

	-- WF.sqlite.index_store
local WFRxIndexStore = require 'WFRxIndexStore'

local WFOzTestUtils = require 'WFOzTestUtils'


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

local logger = WFLogger( 'WFCatSearchByRatingTest' )

--local runUntilDone = WFRxRunUntilDone


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

local WFCatSearchByRatingTest = {}

local kUserId = string.rep( '115e7000', 4 )

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

local sCoveragePath

function WFCatSearchByRatingTest.setUp( inCoveragePath )
	sCoveragePath = inCoveragePath
end

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

local function addRatingsToAssetFn( )
	local counter = 1

	return function( docValue )
		
		docValue.importSource.originalHeight = counter + 1
				
		docValue.ratings = {
					[ kUserId ] = {
						rating = math.mod( counter, 6 ),
					},
				}
		
		counter = counter + 1
		
		return docValue
	end

end

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

local function makeBulkAdderOfAsset( rxTest, docStore )

	local counter = 0

	return function( n )
		local array = {}
		for i = 1, n do
			local day = 1 + math.mod( counter, 28 )
			local month = 1 + math.mod( math.floor( counter / 28 ), 12 )
			local year = 2000 + math.floor( counter / 28 / 12 )
					
			local docValue = WFOzTestUtils.v2.makeBaseValidAssetDocument( string.format( '%032x', counter ) )
			
			docValue.importSource.originalHeight = counter + 1
			docValue.ratings = {
					[ kUserId ] = {
						rating = math.mod( counter, 6 ),
					},
				}
				
			docValue.captureDate = string.format( "%04d-%02d-%02dT01:02:03.04",
					year, month, day )

			array[ i ] = docValue 
			
			counter = counter + 1
		end

		rxTest:expectSingleValue(

			docStore:bulkSetDocValue( array ),

			':ignore:' )

	end

end

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

local function makeSearcher( rxTest, docStore, indexStore, searchSchema )
	return function( predicates, optSql )
		local terms = WFCatSearchQuery.createQueryParamsStream( searchSchema, {
			predicates = predicates
		} )

		local query2 = WFCatSearchQuery.privateUnitTestExports.uncalmedResultSetQuery( indexStore,
			[[SELECT docId FROM assets @JOIN ORDER BY height DESC]],
			terms,
			'assets.docId'
		)

		return rxTest:observe( query2 )
	end

end

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

function WFCatSearchByRatingTest.rxTestSavedRatingSearch( rxTest )

	rxTest:setTimeLimit( 20 )

	local docStore = WFRxDocStore( ':memory:' )
	local indexStore = WFRxIndexStore( docStore, 'WFCatIndexDefinitions.lua' )

	rxTest:finally( function()

		if sCoveragePath and indexStore and not WFCloseSupport.hasBeenOrWillBeClosed( indexStore ) then
			indexStore:DEBUG_dumpCoverage( sCoveragePath )
		end

		indexStore:close()
		indexStore = nil

		docStore:close()
		docStore = nil

	end )

	local searchSchema = WFCatSearchSchema()

	require 'WFCatSearchByRating'.addSearchToSearchSchema( searchSchema )

	local addAssetFn = WFOzTestUtils.v2.makeAdderOfAsset( rxTest, docStore, addRatingsToAssetFn() )

	for i = 1, 10 do
		addAssetFn( )
	end

	local observeQueryOfTermsFromSavedSearch = makeSearcher( rxTest, docStore, indexStore, searchSchema )

	observeQueryOfTermsFromSavedSearch {
		type = 'rating',
		rating = 3,
		user = kUserId,
		operator = '==',
	}
	:expectDataWithinTime( 5, { { 9 }, { 3 } } )

end

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

function WFCatSearchByRatingTest.DISABLED_rxTestSavedRatingSearch_30000_testPerformance( rxTest )

	rxTest:setTimeLimit( 400 )

	local docStore = WFRxDocStore( ':memory:' )

	local indexStore = WFRxIndexStore( docStore, 'WFCatIndexDefinitions.lua' )

	local searchSchema = WFCatSearchSchema()

	require 'WFCatSearchByRating'.addSearchToSearchSchema( searchSchema )
	require 'WFCatSearchByCaptureDate'.addSearchToSearchSchema( searchSchema )

	local assetCountQuery = WFCatSearchQuery.count( indexStore )

	assetCountQuery = rxTest:observe( assetCountQuery )

	local addAssetsFn = makeBulkAdderOfAsset( rxTest, docStore )

	local NUMBER_OF_ASSETS = 1000
	for i = 1, math.floor( NUMBER_OF_ASSETS / 100 ) do
		if math.mod( i, 100 ) == 0 then
			logger:warn( "%02d%%", math.floor( 100 * 100 * i / NUMBER_OF_ASSETS ) )
		end
		addAssetsFn( 100 )
	end

	assetCountQuery:expectDataWithinTime( 30, NUMBER_OF_ASSETS )

	logger:warn( "Count confirmed." )

	local observeQueryOfTermsFromSavedSearch = makeSearcher( rxTest, docStore, indexStore, searchSchema )

	observeQueryOfTermsFromSavedSearch {
		type = 'and',
		terms = {
			{
				type = 'rating',
				rating = 5,
				user = kUserId,
				operator = '==',
			},
			{
				type = 'captureDate',
				captureDate = '2000-01-10',
				operator = '<',
			},
		}
	}
	:expectDataWithinTime( 5, {
		{ 6 },
	} )

	logger:warn( "Easy search complete." )

	observeQueryOfTermsFromSavedSearch( {
		type = 'and',
		terms = {
			{
				type = 'rating',
				rating = 0,
				user = kUserId,
				operator = '>=',
			},
		}
	}, [[SELECT count( docId ) FROM assets @JOIN]] )
	:expectDataWithinTime( 5, { { NUMBER_OF_ASSETS } } )

	logger:warn( "Hard search complete." )

--[[--

	-- Diagnostic log can be used to assess whether indices are required.

	local Rx = require 'Rx'

	local Observable = Rx.Observable

	rxTest:observe( Observable.create( function( observer )
		local WFDiagnosticLog = require 'WFDiagnosticLog'
		local reportP = WFDiagnosticLog.generateHtmlReportP{
			outputForAutomation = true,
		}
		local action = reportP:whenResolvedDo( function( status, ... )
			if status == 'data' then
				observer:onNext( ... )
				observer:onCompleted()
			end
			if status == 'error' then
				observer:onError( ... )
			end
		end )
		action:call( runUntilDone )
		return function()
			action:close()
		end
	end )
	:map( function( htmlReport )
		logger:warn( htmlReport )
		return true
	end ) )
	:expectData( true )
--]]--

end

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

return WFRxTestCase.wrapSuite( 'WFCatSearchByRatingTest', WFCatSearchByRatingTest )
