function ampcblock_MaskInitFcnResize(blk,nv,nu,ny,nCC)
% Adaptive MPC block uses three functions in the following order to
% initialize:
%
%   InitFcn: collect data from @mpc and @mpcstate objects specified in the
%   block dialog.  Obtain additional inport and outport connection
%   information (i.e. optional ports on/off status, whether an inport is
%   connected to a source block), special mmpc settings, and some scaling
%   data.  Save the structure to block "UserData".
%
%   MaskInitFcn: split into two functions: Parameter and Resize.
%
%       Parameter: when "UserData" is empty (i.e. model opens or no @mpc),
%       initialize the block with correct information for compilation.
%       Otherwise, create mask variables from "UserData" with additional
%       sanity check and memory optimization.
%
%       Resize: modify the block I/O based on dialog settings.  Each
%       constant block (when an optional inport is off) is initialized with
%       correct dimension.
%
%   StartFcn: check signal connectivity to MPC Controller block.  Signal
%   dimensions are already checked in the C S-function blocks connected to
%   the inports.  This function is called after compilation is done.

%   Authors: A. Bemporad, N. L. Ricker, R. Chen
%   Copyright 1986-2017 The MathWorks, Inc.

%% Obtain current availability of the optional in/out ports in the block
AvailableBlocks = get_param(blk,'Blocks');
type_in_block = ismember({'md','ext.mv','umin','umax','ymin','ymax','E','S','switch','y.wt','u.wt','du.wt','ecr.wt','mv.target','p','m'},AvailableBlocks);
type_out_block = ismember({'cost','mv.seq','x.seq','y.seq','qp.status','est.state'},AvailableBlocks);

%% Obtain availability of the optional in/out ports from the block dialog
type_in_mask = [...
                strcmp(get_param(blk,'md_inport'),'on'), ...
                strcmp(get_param(blk,'mv_inport'),'on'),...
                strcmp(get_param(blk,'umin_inport'),'on'),...
                strcmp(get_param(blk,'umax_inport'),'on'),...
                strcmp(get_param(blk,'ymin_inport'),'on'),...
                strcmp(get_param(blk,'ymax_inport'),'on'),...
                strcmp(get_param(blk,'cc_inport'),'on'),...
                strcmp(get_param(blk,'cc_inport'),'on') && strcmp(get_param(blk,'md_inport'),'on'),...
                strcmp(get_param(blk,'switch_inport'),'on'),...
                strcmp(get_param(blk,'ywt_inport'),'on'),...
                strcmp(get_param(blk,'uwt_inport'),'on'),...
                strcmp(get_param(blk,'duwt_inport'),'on'),...
                strcmp(get_param(blk,'rhoeps_inport'),'on'),...
                strcmp(get_param(blk,'uref_inport'),'on'),...
                strcmp(get_param(blk,'pm_inport'),'on'),...  
                ];
type_out_mask = [...
                strcmp(get_param(blk,'return_cost'),'on'),...
                strcmp(get_param(blk,'return_mvseq'),'on'), ...
                strcmp(get_param(blk,'return_xseq'),'on'), ...
                strcmp(get_param(blk,'return_ovseq'),'on'), ...
                strcmp(get_param(blk,'return_qpstatus'),'on'), ...
                strcmp(get_param(blk,'return_state'),'on'), ...
                ];

%% Update MO or X
maskdisplay=get_param(blk,'MaskDisplay');
CustomEstimation = strcmp(get_param(blk,'state_inport'),'on');
if CustomEstimation
    label = '''mo''';
    pos = strfind(maskdisplay, label);
    if ~isempty(pos)
        % Change mo inport to x inport
        maskdisplay = [maskdisplay(1:pos-1),'''x[k|k]''',maskdisplay(pos+length(label):end)];
        delete_line([blk,'/MPC'],'moorx/1','optimizer/3');
        delete_line([blk,'/MPC'],'last_x/1','optimizer/1');
        delete_line([blk,'/MPC'],'ym_zero/1','x_terminator/1');
        add_line([blk,'/MPC'],'moorx/1','optimizer/1','AutoRouting','on');
        add_line([blk,'/MPC'],'last_x/1','x_terminator/1','AutoRouting','on');
        add_line([blk,'/MPC'],'ym_zero/1','optimizer/3','AutoRouting','on');
    end
else
    label = '''x[k|k]''';
    pos = strfind(maskdisplay, label);
    if ~isempty(pos)
        % Change x inport to mo inport
        maskdisplay = [maskdisplay(1:pos-1),'''mo''',maskdisplay(pos+length(label):end)];
        delete_line([blk,'/MPC'],'moorx/1','optimizer/1');
        delete_line([blk,'/MPC'],'last_x/1','x_terminator/1');
        delete_line([blk,'/MPC'],'ym_zero/1','optimizer/3');
        add_line([blk,'/MPC'],'moorx/1','optimizer/3','AutoRouting','on');
        add_line([blk,'/MPC'],'last_x/1','optimizer/1','AutoRouting','on');
        add_line([blk,'/MPC'],'ym_zero/1','x_terminator/1','AutoRouting','on');
    end
end

%% Reset mask display to three inports (Model, MO/X, REF) and one outport (MV)
aux = 'port_label(''input'', 3, ''ref'')';
pos = strfind(maskdisplay,aux)+length(aux);
maskdisplay = maskdisplay(1:pos-1);
nextInport = 4;
nextOutport = 2;

%% Update MD
[maskdisplay, nextInport] = mpc_update_inport(blk,AvailableBlocks,type_in_mask,type_in_block,1,'md',nextInport,3,maskdisplay);

%% Update EXT.MV
[maskdisplay, nextInport] = mpc_update_inport(blk,AvailableBlocks,type_in_mask,type_in_block,2,'ext.mv',nextInport,4,maskdisplay);

%% Update LIMITS
[maskdisplay, nextInport] = mpc_update_inport(blk,AvailableBlocks,type_in_mask,type_in_block,3,'umin',nextInport,5,maskdisplay);
[maskdisplay, nextInport] = mpc_update_inport(blk,AvailableBlocks,type_in_mask,type_in_block,4,'umax',nextInport,6,maskdisplay);
[maskdisplay, nextInport] = mpc_update_inport(blk,AvailableBlocks,type_in_mask,type_in_block,5,'ymin',nextInport,7,maskdisplay);
[maskdisplay, nextInport] = mpc_update_inport(blk,AvailableBlocks,type_in_mask,type_in_block,6,'ymax',nextInport,8,maskdisplay);

%% Update Custom Constraints (E/F/G)
[maskdisplay, nextInport] = mpc_update_inport(blk,AvailableBlocks,type_in_mask,type_in_block,7,'E',nextInport,9,maskdisplay);
[maskdisplay, nextInport] = mpc_update_inport(blk,AvailableBlocks,type_in_mask,type_in_block,7,'F',nextInport,10,maskdisplay);
[maskdisplay, nextInport] = mpc_update_inport(blk,AvailableBlocks,type_in_mask,type_in_block,7,'G',nextInport,11,maskdisplay);

%% Update Custom Constraints S
[maskdisplay, nextInport] = mpc_update_inport(blk,AvailableBlocks,type_in_mask,type_in_block,8,'S',nextInport,12,maskdisplay);

%% Update SWITCH
[maskdisplay, nextInport] = mpc_update_inport(blk,AvailableBlocks,type_in_mask,type_in_block,9,'switch',nextInport,13,maskdisplay);

%% Update YWT
[maskdisplay, nextInport] = mpc_update_inport(blk,AvailableBlocks,type_in_mask,type_in_block,10,'y.wt',nextInport,14,maskdisplay);

%% Update UWT
[maskdisplay, nextInport] = mpc_update_inport(blk,AvailableBlocks,type_in_mask,type_in_block,11,'u.wt',nextInport,15,maskdisplay);

%% Update DUWT
[maskdisplay, nextInport] = mpc_update_inport(blk,AvailableBlocks,type_in_mask,type_in_block,12,'du.wt',nextInport,16,maskdisplay);

%% Update RHOEPS
[maskdisplay, nextInport] = mpc_update_inport(blk,AvailableBlocks,type_in_mask,type_in_block,13,'ecr.wt',nextInport,17,maskdisplay);

%% Update UREF
[maskdisplay, nextInport] = mpc_update_inport(blk,AvailableBlocks,type_in_mask,type_in_block,14,'mv.target',nextInport,18,maskdisplay);

%% Update PM
[maskdisplay, nextInport] = mpc_update_inport(blk,AvailableBlocks,type_in_mask,type_in_block,15,'p',nextInport,27,maskdisplay);
[maskdisplay, nextInport] = mpc_update_inport(blk,AvailableBlocks,type_in_mask,type_in_block,15,'m',nextInport,28,maskdisplay);

%% Update COST
[maskdisplay, nextOutport] = mpc_update_outport(blk,AvailableBlocks,type_out_mask,type_out_block,1,'cost',nextOutport,2,maskdisplay);

%% Update MV SEQUENCE
[maskdisplay, nextOutport] = mpc_update_outport(blk,AvailableBlocks,type_out_mask,type_out_block,2,'mv.seq',nextOutport,3,maskdisplay);

%% Update X SEQUENCE
[maskdisplay, nextOutport] = mpc_update_outport(blk,AvailableBlocks,type_out_mask,type_out_block,3,'x.seq',nextOutport,4,maskdisplay);

%% Update OV SEQUENCE
[maskdisplay, nextOutport] = mpc_update_outport(blk,AvailableBlocks,type_out_mask,type_out_block,4,'y.seq',nextOutport,5,maskdisplay);

%% Update QPSTATUS
[maskdisplay, nextOutport] = mpc_update_outport(blk,AvailableBlocks,type_out_mask,type_out_block,5,'qp.status',nextOutport,6,maskdisplay);

%% Update Estimated State
[maskdisplay, nextOutport] = mpc_update_outport(blk,AvailableBlocks,type_out_mask,type_out_block,6,'est.state',nextOutport,7,maskdisplay);

%% Update Mask Display
set_param(blk,'MaskDisplay',maskdisplay);

%% Now set correct dimensions for zero signals
AvailableBlocks = get_param(blk,'Blocks');
if ismember('md_zero',AvailableBlocks)
    set_param([blk '/md_zero'],'Value',sprintf('zeros(%d,1)',max(nv-1,1)));
end
if ismember('ext.mv_zero',AvailableBlocks)
    set_param([blk '/ext.mv_zero'],'Value',sprintf('zeros(%d,1)',nu));
end
if ismember('umin_zero',AvailableBlocks)
    set_param([blk '/umin_zero'],'Value',sprintf('zeros(%d,1)',nu));
end
if ismember('umax_zero',AvailableBlocks)
    set_param([blk '/umax_zero'],'Value',sprintf('zeros(%d,1)',nu));
end
if ismember('ymin_zero',AvailableBlocks)
    set_param([blk '/ymin_zero'],'Value',sprintf('zeros(%d,1)',ny));
end
if ismember('ymax_zero',AvailableBlocks)
    set_param([blk '/ymax_zero'],'Value',sprintf('zeros(%d,1)',ny));
end
if ismember('E_zero',AvailableBlocks)
    set_param([blk '/E_zero'],'Value',sprintf('zeros(%d,%d)',max(nCC,1),nu),'VectorParams1D','off');
end
if ismember('F_zero',AvailableBlocks)
    set_param([blk '/F_zero'],'Value',sprintf('zeros(%d,%d)',max(nCC,1),ny),'VectorParams1D','off');
end
if ismember('G_zero',AvailableBlocks)
    set_param([blk '/G_zero'],'Value',sprintf('zeros(%d,1)',max(nCC,1)),'VectorParams1D','off');
end
if ismember('S_zero',AvailableBlocks)
    set_param([blk '/S_zero'],'Value',sprintf('zeros(%d,%d)',max(nCC,1),max(nv-1,1)),'VectorParams1D','off');
end
if ismember('switch_zero',AvailableBlocks)
    set_param([blk '/switch_zero'],'Value',sprintf('zeros(%d,1)',1));
end
if ismember('y.wt_zero',AvailableBlocks)
    set_param([blk '/y.wt_zero'],'Value',sprintf('zeros(%d,1)',ny));
end
if ismember('u.wt_zero',AvailableBlocks)
    set_param([blk '/u.wt_zero'],'Value',sprintf('zeros(%d,1)',nu));
end
if ismember('du.wt_zero',AvailableBlocks)
    set_param([blk '/du.wt_zero'],'Value',sprintf('zeros(%d,1)',nu));
end
if ismember('ecr.wt_zero',AvailableBlocks)
    set_param([blk '/ecr.wt_zero'],'Value',sprintf('zeros(%d,1)',1));
end
if ismember('mv.target_zero',AvailableBlocks)
    set_param([blk '/mv.target_zero'],'Value',sprintf('zeros(%d,1)',nu));
end
