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

WFCatSearchSortOnlineHandler.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'
local Observable = Rx.Observable
local WFRxRunUntilDone = require 'WFRxRunUntilDone'

local WFCatSearchOnlineRequest = require "WFCatSearchOnlineRequest"
local WFCatSearchAndSortConstants = require "WFCatSearchAndSortConstants"
local WFCatOnlineSearchResultTableHandler = require 'WFCatOnlineSearchResultTableHandler'

local KSTableUtils = require "KSTableUtils"
local WFArguments = require 'WFArguments'

local OnlineSearchStatus = WFCatSearchAndSortConstants.OnlineSearchStatus

local check = assert( WFArguments.check )

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

local WFCatSearchSortOnlineHandler = {}

------------------------------------------------------------
local function getCatalogInfoDataObservable( wfCatalogModel )
	
	local catalogInfoObservable = wfCatalogModel
			:take( 1 )
			:flatMap( function( wfCatalog )
				
				local wfCatUser
				
				-- may be test catalog ?
				if wfCatalog.ozUser then
					wfCatUser = wfCatalog:ozUser()
				end
				
				return Observable.just( wfCatalog, wfCatUser )
				
			end )
	
	return catalogInfoObservable
end

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

local function placeSearchRequest( wfCatalog, wfCatUser, queryId, searchTerms )
	
	local url = WFCatSearchAndSortConstants.getSearchUrl()
	local currentOnlineSearchRequest = WFCatSearchOnlineRequest( searchTerms )
	
	return currentOnlineSearchRequest:executeOnlineSearch( 
					wfCatUser, url, WFCatSearchAndSortConstants.getSearchRequestArgs() )
		
		:tap( function( status )
			
			WFCatOnlineSearchResultTableHandler.updateSearchTable( wfCatalog, queryId, status.newResults )
			
		end )
		
		:finally( function()
			
			currentOnlineSearchRequest:closeRequest()
			currentOnlineSearchRequest:dispose()
			
		end )
		
end

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

local function mapFacetValuesMapToList( facetsValuesMap )
	
	local facetsList = {}
	
	for facetValue, facetInfo in pairs( facetsValuesMap ) do
		
		table.insert( facetsList, {
			value = facetValue,
			count = facetInfo.count,
			display_name = facetInfo.display_name
		} )
		
	end
	
	return facetsList
	
end

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

function WFCatSearchSortOnlineHandler.initializeSearchDetails( catalogModel, userProvidedTerms )
	
	check( '_', 'table' )
	
	return getCatalogInfoDataObservable( catalogModel )
		
		:flatMap( function( wfCatalog, wfCatUser )
			
			WFCatOnlineSearchResultTableHandler.clearSearchTable( wfCatalog )
			
			local requestObservables = {}
			
			for queryId, userTerms in pairs( userProvidedTerms ) do
				
				local requestObs = placeSearchRequest( wfCatalog, wfCatUser, queryId, userTerms )
				table.insert( requestObservables, requestObs )
				
			end
			
			return Rx.Observable.combineLatest( unpack( requestObservables ) )
				
				:map( function( ... )
					
					local combinedStatus = {}
					
					local totalAvailable = 0
					local executionStatus = OnlineSearchStatus.InProgress
					
					local statuses = pack( ... )
					
					local requestsCount = #statuses
					local completedCount = 0
					
					for _, status in ipairs( statuses ) do
						
						if status.totalAvailable then
							totalAvailable = totalAvailable + status.totalAvailable
						end
						
						if status.executionStatus == OnlineSearchStatus.Completed 
								or status.executionStatus == OnlineSearchStatus.CompletedUnexpectedly then
							completedCount = completedCount + 1
							
						end
						
					end
					
					if completedCount == requestsCount then
						executionStatus = OnlineSearchStatus.Completed
					end
					
					combinedStatus.totalAvailable = totalAvailable
					combinedStatus.executionStatus = executionStatus
					
					return combinedStatus
					
				end )			
			
		end )
	
end

--------------------------------------------------------------------------------
function WFCatSearchSortOnlineHandler.searchFacetValues( catalogModel, userProvidedTerms )
	
	local searchRequestObservable = getCatalogInfoDataObservable( catalogModel )
		
		:flatMap( function ( wfCatalog, wfCatUser )
			local url = WFCatSearchAndSortConstants.getSearchUrl()
			
			local requestObservables = {}
			
			for queryId, userTerms in pairs( userProvidedTerms ) do
				
				local searchOnlineRequest = WFCatSearchOnlineRequest( userTerms )
				
				local requestObs = searchOnlineRequest:executeFacetValuesSearch( 
							wfCatUser, url, WFCatSearchAndSortConstants.getSearchRequestArgs() )
				
				table.insert( requestObservables, requestObs )
				
			end
			
			return Rx.Observable.combineLatest( unpack( requestObservables ) )
				
				:map( function( ... )
					
					local combinedResults = {}
					
					local allResults = pack( ... )
					
					for _, facetsMap in ipairs( allResults ) do
						
						-- Ex: facetField = "lightroom_keyword_lc"
						-- Ex: facetValues = [ { value = k1, count = 10, display_name = k1 } ]
						for facetField, facetValues in pairs( facetsMap ) do
							
							-- Ex: combinedResults = { lightroom_keyword_lc = { k1 = { count = 5, display_name = "k1" } }}
							-- Ex: currentFacets = { k1 = { count = 5, display_name = "k1" } }
							local currentFacets = combinedResults[ facetField ] or {}
							
							for _, facetValue in ipairs( facetValues ) do
								
								local currentCount = KSTableUtils.derefOpt( currentFacets, facetValue.value, "count" ) or 0
								local newCount = facetValue.count or 0
								local updatedCount = currentCount + newCount
								
								currentFacets[ facetValue.value ] = {
									count = updatedCount,
									display_name = facetValue.display_name
								}
								
							end
							
							combinedResults[ facetField ] = currentFacets
							
						end
						
					end
					
					local retVal = {}
					
					for facetField, facetValuesMap in pairs( combinedResults ) do
						
						retVal[ facetField ] = mapFacetValuesMapToList( facetValuesMap )
						
					end
					
					return retVal
					
				end )
				
		end )
		
		:call( WFRxRunUntilDone ) 
	
	return searchRequestObservable

end

--------------------------------------------------------------------------------
function WFCatSearchSortOnlineHandler.categoryKeys( catalogModel, userProvidedTerms )
	
	local searchRequestObservable = getCatalogInfoDataObservable( catalogModel )
		
		:flatMap( function ( wfCatalog, wfCatUser )
		
			local isStage = userProvidedTerms.isStage
			userProvidedTerms.isStage = nil
			
			local url = WFCatSearchAndSortConstants.getSearchUrl( isStage )
			
			local searchOnlineRequest = WFCatSearchOnlineRequest( userProvidedTerms )
			
			return searchOnlineRequest:executeCategoryKeysSearch( 
						wfCatUser, url, WFCatSearchAndSortConstants.getSearchRequestArgs() )
		end )
		
		:call( WFRxRunUntilDone ) 
	
	return { value = searchRequestObservable }

end

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

function WFCatSearchSortOnlineHandler.getAutoCompleteValues( catalogModel, searchParams )
	
	local searchRequestObservable = getCatalogInfoDataObservable( catalogModel )
		
		:flatMap( function ( wfCatalog, wfCatUser )
			local url = WFCatSearchAndSortConstants.getAutoCompleteURL( searchParams )
			
			local searchOnlineRequest = WFCatSearchOnlineRequest( {} )	-- empty body since it is a GET request
			
			return searchOnlineRequest:executeAutoComplete( 
						wfCatUser, url, WFCatSearchAndSortConstants.getAutoCompleteRequestArgs() )
		end )
		
		:call( WFRxRunUntilDone ) 
	
	return { value = searchRequestObservable }

end

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

return WFCatSearchSortOnlineHandler
