function varargout = fdesignblkfcn(hBlk, classname)
%FDESIGNBLKFCN   Gateway for Filter Design blocks.

%   Copyright 2006-2023 The MathWorks, Inc.

if nargout
    [varargout{1:nargout}] = feval(classname{1}, hBlk, classname{2:end});
else
    feval(classname{1}, hBlk, classname{2:end});
end

% ------------------------------------------------------------------
function h = OpenFcn(hBlk, classname)
% hBlk - Handle to the block we are opening.
% classname - constructor to the design object.

if isLockedModel(hBlk)
    h = FilterDesignBlockDialog.DesignBlock(hBlk, classname);
    % Suppress meaningless UDD errors from FDESIGN
    return;
end

hDesigner = getObject(hBlk);
if isempty(hDesigner)
    % R2009b and before, userdata was not saved,
    % Set implementation options to pre-R2011a hard coded values
    h = FilterDesignBlockDialog.DesignBlock(hBlk, classname);
    hDesigner = h.CurrentDesigner;
    hDesigner.InputProcessing         = 'elementsaschannels';
    hDesigner.RateOption              = 'allowmultirate';
    hDesigner.BuildUsingBasicElements = true;
    hDesigner.OptimizeZeros           = false;
    hDesigner.OptimizeOnes            = false;
    hDesigner.OptimizeNegOnes         = false;
    hDesigner.OptimizeDelays          = false;
    hDesigner.OptimizeUnitScaleValues = false;
    hDesigner.UseSymbolicNames        = false;
    setObject(hBlk, hDesigner);
end

h = FilterDesignBlockDialog.DesignBlock(hBlk, hDesigner);
if ~isa(hDesigner, 'FilterDesignDialog.AbstractDesign')
    hDesigner = h.CurrentDesigner;
    setObject(hBlk, hDesigner);
end

% Attach a listener to the DialogApplied event of the designer.  This event
% will "dirty" the block and attempt to refresh the contained system.
l = event.listener(hDesigner, 'DialogApplied', @(hSrc, ed) dialogApplied(hBlk, hDesigner));
if ~isprop(h, 'DialogAppliedListener')
    addprop(h,'DialogAppliedListener');
end
set(h, 'DialogAppliedListener', l);


% ------------------------------------------------------------------
function CopyFcn(hBlk)

set(hBlk, 'LinkStatus', 'none');

% ------------------------------------------------------------------
function InitFcn(hBlk)

hDesigner = getObject(hBlk);
if isempty(hDesigner)
    return;
end


try
    [Hd, sameDesign] = design(hDesigner);
catch e
    % same must be defined to avoid assertions.
    sameDesign = true; %#ok<NASGU>
    
    % Cache the last error string.
    errStr = cleanerrormsg(e.message);
    
    error(message('FilterDesignLib:fdesignblkfcn:InvalidDesign', errStr));
end

% Get the implementation options
laState = get(hDesigner, 'LastAppliedState');
impl = getImplementationOptions(hDesigner,laState);
oldImpl = get(hDesigner,'LastAppliedImplementationOpts');
% Inherited input processing is removed. If the model was saved with
% 'Inherited', we have to redesign with frame-based
if isfield(laState,'InputProcessing') && strcmp(get(hDesigner,'InputProcessing'),laState.InputProcessing)
    sameImplementation = isequal(impl,oldImpl);
else
    sameImplementation = false;
end
%sameImplementation = false;

if sameDesign && sameImplementation
    % Model should already be up to date.
    return;
else
    generateModel(hDesigner,hBlk,Hd);
end

% design() may change the "LastAppliedSpec" and generateModel() may change
% "LastAppliedImplementationOpts"
setObject(hBlk, hDesigner);

% -------------------------------------------------------------------------
function dialogApplied(hBlk, hDesigner)

try
    % Set the designer object on the user data but do not overwrite the
    % LastAppliedImplementationOpts value since this value is used to
    % determine if we need to compute a new model or if we can reuse the
    % existing one.
    udOld = get(hBlk,'UserData');
    saveImOptsFlag = ~isempty(udOld) && isfield(udOld, 'LastAppliedImplementationOpts');
    if saveImOptsFlag
        oldImpOpts = udOld.LastAppliedImplementationOpts ;
    end
    
    setObject(hBlk, hDesigner);
    
    if saveImOptsFlag
        ud = get(hBlk,'UserData');
        ud.LastAppliedImplementationOpts = oldImpOpts;
        set(hBlk,'UserData',ud);
    end
    
    InitFcn(hBlk);
catch me
    error(message('FilterDesignLib:fdesignblkfcn:InvalidDesignOpts', cleanerrormsg( me.message )));
end

%---------------------------------------------------------------
function setObject(hBlk, hDesigner)

set(hBlk, 'UserData', saveobj(hDesigner));

%---------------------------------------------------------------
function hDesigner = getObject(hBlk)

ud = get(hBlk, 'UserData');
hDesigner = [];
if isstruct(ud)
    hDesigner = feval([ud.class '.load'], ud);
end

%---------------------------------------------------------------
function boolflag = isLockedModel(hBlk)
%ISLOCKEDMODEL returns 1 for a locked model and 0 for an unlocked model
% Input can be either hBlk or hFDA.

% Get the handle to the model and get its locked status.
hModel = bdroot(hBlk);

boolflag = strcmpi(get_param(hModel, 'lock'), 'on');

% [EOF]
