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

WFCatSearchQueryTest.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.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 WFCatSearchQueryTest = {}

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

local sCoveragePath

function WFCatSearchQueryTest.setUp( inCoveragePath )
	sCoveragePath = inCoveragePath
end

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

local function addCaptureDateFn( )
	local counter = 1

	return function( docValue, date )
		
		docValue.importSource.originalHeight = counter + 1
		docValue.captureDate = date

		counter = counter + 1
		
		return docValue
	end

end

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

--[[
local function makeBulkAdderOfAssetWithCaptureDate( 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 )
			array[ i ] = {
				type = 'asset',
				subtype = 'image',
				_id = string.format( '%032x', counter ),
				importSource = {
					originalWidth = 1,
					originalHeight = counter + 1,
				},
				captureDate = string.format( "%04d-%02d-%02dT01:02:03.04",
					year, month, day )
			}
			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 WFCatSearchQueryTest.rxTestSavedDateSearch( 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 'WFCatSearchByCaptureDate'.addSearchToSearchSchema( searchSchema )

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

	addAssetFn( '1973-03-08T01:02:03.04' )
	addAssetFn( '1995-05-27T14:00:00.00' )
	addAssetFn( '2006-01-20T16:00:00.00' )

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

	observeQueryOfTermsFromSavedSearch {
		type = 'month',
		month = 3,
		operator = '==',
	}
	:expectDataWithinTime( 5, { { 1 } } )

	local query2 = observeQueryOfTermsFromSavedSearch {
		type = 'dayOfMonth',
		dayOfMonth = 15,
		operator = '>',
	}

	query2:expectDataWithinTime( 5, { { 3 }, { 2 } } )

	addAssetFn( '2015-05-27T24:00:00.00' )

	query2:expectDataWithinTime( 5, { { 4 }, { 3 }, { 2 } } )

	observeQueryOfTermsFromSavedSearch {
		type = 'and',
		terms = {
			{
				type = 'month',
				month = 5,
				operator = '==',
			},
			{
				type = 'dayOfMonth',
				dayOfMonth = 27,
				operator = '==',
			}
		}
	}
	:expectDataWithinTime( 5, { { 4 }, { 2 } } )

	observeQueryOfTermsFromSavedSearch {
		type = 'or',
		terms = {
			{
				type = 'captureDate',
				captureDate = '1985',
				operator = '<',
			},
			{
				type = 'captureDate',
				captureDate = '2010',
				operator = '>',
			}
		}
	}
	:expectDataWithinTime( 5, { { 4 }, { 1 } } )

end

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

-- SPAM [jandrew 10/2/2015]: This test is flaky. @arahn said it's okay to disable for now.

--[[

function WFCatSearchQueryTest.rxTestSavedDateSearch_10000_testPerformance( rxTest )

	rxTest:setTimeLimit( 400 )

	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 'WFCatSearchByCaptureDate'.addSearchToSearchSchema( searchSchema )

	local assetCountQuery = WFCatSearchQuery.count( indexStore )

	assetCountQuery = rxTest:observe( assetCountQuery )

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

	assetCountQuery:expectData( N )

	logger:warn( "Count confirmed." )

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

	observeQueryOfTermsFromSavedSearch {
		type = 'and',
		terms = {
			{
				type = 'month',
				month = 3,
				operator = '==',
			},
			{
				type = 'dayOfMonth',
				dayOfMonth = 8,
				operator = '==',
			},
			{
				type = 'year',
				year = 2003,
				operator = '<',
			},
		}
	}
	:expectData {
		{ 2 * 12 * 28 + 28 * ( 3 - 1 ) + 8 },
		{ 1 * 12 * 28 + 28 * ( 3 - 1 ) + 8 },
		{ 0 * 12 * 28 + 28 * ( 3 - 1 ) + 8 },
	}

	logger:warn( "Easy search complete." )

	observeQueryOfTermsFromSavedSearch( {
		type = 'and',
		terms = {
			{
				type = 'month',
				month = 1,
				operator = '>=',
			},
			{
				type = 'dayOfMonth',
				dayOfMonth = 1,
				operator = '>=',
			},
			{
				type = 'year',
				year = 2000,
				operator = '>=',
			},
		} ]]--
	-- }, [[SELECT count( docId ) FROM assets @JOIN]] )
	--[[:expectData{ { N } }

	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( WFCatSearchQueryTest )
