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

DesktopModelUtils.lua

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

ADOBE CONFIDENTIAL
------------------
Copyright 2023 Adobe
All Rights Reserved.

NOTICE: All information contained herein is, and remains
the property of Adobe and its suppliers, if any. The intellectual
and technical concepts contained herein are proprietary to Adobe
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.

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

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

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._isDesktopHighFidelityModel and
			modelParams.deliverAllValues then

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

	end

	return modelParams

end

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

makeWarnIfDeliverAllValues = function( maybeModelsTable )

	return wrapModelMethods( maybeModelsTable, warnIfDeliverAllValues )

end

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

local function addDeliverAllValues( modelName, modelParams )

	modelParams = warnIfDeliverAllValues( modelName, modelParams )

	modelParams._isDesktopHighFidelityModel = true
	
	modelParams.deliverAllValues = true

	return modelParams

end

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

local function makeDeliverAllValuesModels( maybeModelsTable )

	return wrapModelMethods( maybeModelsTable, addDeliverAllValues )

end

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

local function makeWFModelDefinition( desktopModelDefinition )

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

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

	local wfModelDefinition = desktopModelDefinition

	local checkedMostRecentValueModels = 
				makeWarnIfDeliverAllValues( 
					desktopModelDefinition.mostRecentValueModels )

	wfModelDefinition.mostRecentValueModels = nil

	local checkedHighFidelityModels = 
				makeDeliverAllValuesModels( 
					desktopModelDefinition.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,

}
