function accblock_callbackCreateSubsystemButton(blk)
% Callback function of the "Create ACC subsystem" button in the Adaptive
% Cruise Control System block dialog.

%   Author: Meng Xia, Rong Chen
%   Copyright 2017-2021 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('accsubsystem', Exclusion);
while true
    filename = evalin('base',['which(''-all'',''' modelname, ''');']);
    if isempty(filename)
        break;
    else
        Exclusion = union(Exclusion, modelname);
        modelname = matlab.lang.makeUniqueStrings('accsubsystem', Exclusion); 
    end
end
% create new model
new_system(modelname);

%% add ACC subsystem block
name = 'ACC 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] = accblock_utilExportDataStruct(blk,modelname,AllNames);

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

%% assign values for acc subsystem
setACCParam(blk,subsystemname,structname);

%% open acc subsystem
open_system(modelname);




%% local function: set ACC parameters using the mpcacc struct
function setACCParam(blk,subsystemname,structname)
% always-have constant blocks
blocknames = { 'Default spacing constant',...
               'Maximum velocity constant',...
               'Minimum velocity constant',...
               };
set_param([subsystemname '/' blocknames{1}],'Value',[structname '.DefaultSpacing']);
set_param([subsystemname '/' blocknames{2}],'Value',[structname '.MaxVelocity']);
set_param([subsystemname '/' blocknames{3}],'Value',[structname '.MinVelocity']);
% optional constant blocks
if strcmp(get_param(blk,'amin_ext'),'off')
    set_param([subsystemname '/' 'Minimum longitudinal acceleration' ' constant'],'Value',[structname '.MinAcceleration']);
end
if strcmp(get_param(blk,'amax_ext'),'off')
    set_param([subsystemname '/' 'Maximum longitudinal acceleration' ' constant'],'Value',[structname '.MaxAcceleration']);
end
% data type in the "Convert" blocks
convertBlocks = find_system(subsystemname,'MatchFilter', @Simulink.match.allVariants, 'BlockType', 'DataTypeConversion' );
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
% data type in the "MPCDataTypeAutoConversion" blocks
MPCConvertBlocks = find_system(subsystemname,'MatchFilter', @Simulink.match.allVariants, 'MaskType', 'MPCDataTypeAutoConversion' );
numMPCConvertBlk = length(MPCConvertBlocks);
for ct = 1:numMPCConvertBlk    
    set_param(MPCConvertBlocks{ct},'datatypestr',[structname '.DataType']);
end
% mpcobj
set_param([subsystemname '/' 'MPC'],'mpcobj',[structname '.Controller']);

    

