function vppblock_callbackCreateSubsystemButton(blk)
% Callback function of the "Create VPP subsystem" button in the Vehicle
% Path Planner (VPP) System block dialog.

%   Copyright 2017-2022 The MathWorks, Inc.

%% create new Simulink model
% find existing diagram name
AllDiagrams = find_system('Type','block_diagram');
AllNames = evalin('base','who');
Exclusion = union(AllDiagrams, AllNames);
% make unique name
modelname = matlab.lang.makeUniqueStrings('vppsubsystem', Exclusion);
while true
    filename = evalin('base',['which(''-all'',''' modelname, ''');']);
    if isempty(filename)
        break;
    else
        Exclusion = union(Exclusion, modelname);
        modelname = matlab.lang.makeUniqueStrings('vppsubsystem', Exclusion); 
    end
end
% create new model
new_system(modelname);

%% add VPP subsystem block
name = 'VPP subsystem';
subsystemname = [modelname,'/' name];
subsystem = add_block(blk,subsystemname);
% change size of the model
set_param(modelname, 'ZoomFactor','FitSystem');
% disable link to library
set_param(subsystem,'LinkStatus','inactive');
% break link to library
set_param(subsystem,'LinkStatus','none');


%% export the data struct to workspace
[~,structname] = vppblock_utilExportDataStruct(blk,modelname,AllNames);

%% unmask the block
set_param(subsystem,'Mask','off');

%% assign values for subsystem
setBlockParam(blk,subsystemname,structname);
setBlockDataType(subsystemname,structname);
%% open vpp subsystem
open_system(modelname);




%% local function: set parameters using the mpcpathplanner struct
function setBlockParam(blk,subsystemname,structname)
% "PathPlanner" subsystem
mpcSubsystem = [subsystemname '/' 'PathPlanner'];
blocknames = { 'Wheelbase constant',...
               'Ego parameters constant',...
               'Index constant'};
index = ['repmat((1:' [structname '.NumberOfStageParameters'] ')'','...
         [structname '.Planner' '.p'] ',1)'];
set_param([mpcSubsystem '/' blocknames{1}],'Value',[structname '.EgoWheelbase']);
set_param([mpcSubsystem '/' blocknames{2}],'Value',[structname '.EgoParameters']);
set_param([mpcSubsystem '/' blocknames{3}],'Value',index);
set_param([mpcSubsystem '/' 'Multistage Nonlinear MPC'],'nlmpcobj',[structname '.Planner']);
% optional constant blocks
if strcmp(get_param(blk,'obs_ext'),'off')
    set_param([subsystemname '/' 'Obstacles' ' constant'],...
        'Value',[structname '.ObstaclesMatrix']);
end
if strcmp(get_param(blk,'v_ext'),'off')
    set_param([subsystemname '/' 'Velocity range' ' constant'],...
        'Value',[structname '.VelocityRange']);
end
if strcmp(get_param(blk,'steer_ext'),'off')
    set_param([subsystemname '/' 'Steering angle range' ' constant'],...
        'Value',[structname '.SteeringRange']);
end
% obstacles spec dimensions
    set_param([subsystemname '/' 'SignalSpecObs'],...
        'Dimensions',[structname '.ObstaclesMatrixDimensions']);

function setBlockDataType(subsystemname,structname)
% data type in the "Spec" blocks
convertBlocks = find_system(subsystemname, ...
   'MatchFilter', @Simulink.match.allVariants, ...
   'BlockType', 'SignalSpecification');
numConvertBlk = length(convertBlocks);
for ct = 1:numConvertBlk    
    set_param(convertBlocks{ct},'OutDataTypeStr',[structname '.DataType']);
end
% data type in the "Constant" blocks
constantBlocks = find_system(subsystemname, ...
   'MatchFilter', @Simulink.match.allVariants, ...
   'BlockType', 'Constant');
numConstantBlk = length(constantBlocks);
for ct = 1:numConstantBlk    
    set_param(constantBlocks{ct},'OutDataTypeStr',[structname '.DataType']);
end


    

