function obj = structToModel(tunableStr,nontunableStr,varargin) %#codegen
% STRUCTTOMODEL Constructs models from codegen compatible structs

% Copyright 2020-2022 The MathWorks, Inc.

coder.inline('always');
narginchk(2,3);
if nargin == 2
    type = 'double';
else
    type = varargin{1};
end

coder.internal.errorIf(~coder.internal.isConst(nontunableStr),...
    'stats:classreg:coderutils:structToModel:ExpectedConstStructForCodegen');

% classification structs
validCLinearStruct = 'incrementalClassificationLinear.fromStruct';
validCStructs = {validCLinearStruct};

% regression structs
validRLinearStruct = 'incrementalRegressionLinear.fromStruct';
validRStructs = {validRLinearStruct};


isValidCModel = isfield(nontunableStr,'FromStructFcn') && ...
    any(strcmp(nontunableStr.FromStructFcn,validCStructs));

isValidRModel = isfield(nontunableStr,'FromStructFcn') && ...
    any(strcmp(nontunableStr.FromStructFcn,validRStructs));


coder.internal.errorIf(~(isValidCModel || isValidRModel),...
    'stats:classreg:coderutils:structToModel:UnsupportedStructForCodegen');

fromStructFcn = str2func(nontunableStr.FromStructFcn);

if isequal(type,'single')
   singleTunableStr = classreg.coderutils.castStructFieldsForCodegen(tunableStr, type);
   singleNontunableStr = classreg.coderutils.castStructFieldsForCodegen(nontunableStr, type);
   % incremental.SimpleLearner will have a PredictorClass property
   singleNontunableStr.PredictorClass = 'single';
   obj = fromStructFcn(singleTunableStr,coder.const(singleNontunableStr));
else
   obj = fromStructFcn(tunableStr,nontunableStr);
end
end


