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

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

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

local logger = require 'WFLogger'( 'NmbModelUtils' )

local function pack( ... )

	return { ... }, select( "#", ... )

end

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

local makeWarnIfDeliverAllValues

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

local function wrapModelMethod( modelName, modelMethod, modelMethodWrapper )

	return function( ... )

		local packedModelParams, nPackedModelParams = 
				pack( modelMethod( ... ) )

		if type( packedModelParams[ 1 ] ) == "table" then

			packedModelParams[ 1 ] = modelMethodWrapper( 
										modelName, packedModelParams[1 ] )
			
			if type( packedModelParams[ 1 ].models ) == "table" then

				packedModelParams[ 1 ].models =
					makeWarnIfDeliverAllValues( 
						packedModelParams[ 1 ].models )

			end

		end

		return unpack( packedModelParams, 1, nPackedModelParams )

	end

end

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

local function wrapModelMethods( maybeModelMethodsTable, modelWrapper )

	local wrappedModelMethodsTable = {}

	for k, v in pairs( maybeModelMethodsTable or {} ) do

		if type( k ) == "string" and type( v ) == "function" then

			v = wrapModelMethod( k, v, modelWrapper )

		end

		wrappedModelMethodsTable[ k ] = v

	end

	return wrappedModelMethodsTable

end

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

local function warnIfDeliverAllValues( modelName, modelParams )

	if not modelParams._isNimbusHighFidelityModel and 
			modelParams.deliverAllValues then

		logger:warnf( "Nimbus submodel named '%s' should not define deliverAllValues. " ..
							"Use highFidelityModels and pass it to NmbModelUtils.makeWFModelDefinition( ... )",
							modelName )

	end

	return modelParams

end

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

makeWarnIfDeliverAllValues = function( maybeModelsTable )

	return wrapModelMethods( maybeModelsTable, warnIfDeliverAllValues )

end

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

local function addDeliverAllValues( modelName, modelParams )

	modelParams = warnIfDeliverAllValues( modelName, modelParams )

	modelParams._isNimbusHighFidelityModel = true
	
	modelParams.deliverAllValues = true

	return modelParams

end

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

local function makeDeliverAllValuesModels( maybeModelsTable )

	return wrapModelMethods( maybeModelsTable, addDeliverAllValues )

end

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

local function makeWFModelDefinition( nmbModelDefinition )

	assert( type( nmbModelDefinition.mostRecentValueModels ) == "table" or
				type( nmbModelDefinition.highFidelityModels ) == "table", 
			"nmbModelDefinition must define define " ..
			"mostRecentValueModels and/or highFidelityModels" )

	assert( nmbModelDefinition.models == nil, 
			"nmbModelDefinition must not define models. It must define " ..
			"mostRecentValueModels and/or highFidelityModels" )

	local wfModelDefinition = nmbModelDefinition

	local checkedMostRecentValueModels = 
				makeWarnIfDeliverAllValues( 
					nmbModelDefinition.mostRecentValueModels )

	wfModelDefinition.mostRecentValueModels = nil

	local checkedHighFidelityModels = 
				makeDeliverAllValuesModels( 
					nmbModelDefinition.highFidelityModels )

	wfModelDefinition.highFidelityModels = nil

	wfModelDefinition.models = {}

	for k, v in pairs( checkedMostRecentValueModels ) do

		if checkedHighFidelityModels[ k ] then

			error( string.format( "Submodel '%s' is defined in both mostRecentValueModels and highFidelityModels", k ) )

		end

		wfModelDefinition.models[ k ] = v

	end

	for k, v in pairs( checkedHighFidelityModels ) do

		wfModelDefinition.models[ k ] = v

	end

	return wfModelDefinition
	
end

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

return {
	
	makeWFModelDefinition = makeWFModelDefinition,

}
