function varargout = extract(obj, block, varargin)
%

%   Copyright 2010-2022 The MathWorks, Inc.

    opts  = obj.validateExtractArgs(varargin{:});
    blockH = Sldv.utils.getObjH(block, true);
    msg = getString(message('Sldv:SubSysExtract:InvalidFirstArg', obj.UtilityName));
    msg_id = 'Sldv:SubSysExtract:InvalidFirstArg';
    if isempty(blockH)
        % If we do not have a valid block handle, just log the most basic 
        % information in deriveSsError.
        obj.Status = false;
        obj.deriveSsError(msg, msg_id, blockH);
    elseif  strcmp(get_param(bdroot(blockH), 'BlockDiagramType'), 'library')
        msg2 = getString(message('Sldv:SubSysExtract:AtomicSubsystemOrSubchart'));
        obj.Status = false;
        obj.deriveSsError([msg ' ' msg2], msg_id, blockH);
    else            
        obj.Status = ...
            Sldv.SubSystemExtract.checkPortConfiguration(blockH);
        if obj.Status
            isAtomicSubchart = Sldv.utils.isAtomicSubchartSubsystem(blockH);
            [status, msg2] = Sldv.SubSystemExtract.checkPorts(blockH);
            if ~status
                obj.deriveSsError([msg ' ' msg2], msg_id, blockH);
                obj.Status = false;                                         
            else
                obj.SubSystemH = blockH;
                obj.IsAtomicSubchart = isAtomicSubchart;
            end
        else
            obj.deriveSsError(msg, msg_id, blockH);
        end
    end
    
    if obj.Status
        blockH = Sldv.utils.getObjH(block, true);
        if ~Sldv.Extract.checkIsActive(blockH)
            obj.Status = false;
            msg2 = getString(message('Sldv:EXTRACT:ContentForExtractionMustNotBe'));
            obj.deriveSsError([msg ' ' msg2], msg_id, blockH);
        else
            obj.OrigModelH = bdroot(obj.SubSystemH);
            obj.Opts = opts;

            obj.invokess2mdl;
            if ~obj.Status
                obj.deriveSs2mdlError;
            else
                origSubsystemName = get_param(obj.SubSystemH,'Name');
		% @todo update the usage of edit-time filter filterOutInactiveVariantSubsystemChoices()
		% instead use the post-compile filter activeVariants() - g2603143
                newSubsystem = find_system(obj.ModelH,'MatchFilter',@Simulink.match.internal.filterOutInactiveVariantSubsystemChoices, 'SID', '1' ); % look only inside active choice of VSS
                newSubsystemH = get_param(newSubsystem, 'Handle'); 
                obj.NewSubsystemH = newSubsystemH; 
                set_param(newSubsystemH,'Name',origSubsystemName);
                try
                    set_param(obj.ModelH,'DVExtractedSubsystem',origSubsystemName);
                catch Mex %#ok<NASGU>
                    add_param(obj.ModelH,'DVExtractedSubsystem',origSubsystemName);
                end      
                if sldvshareprivate('util_is_analyzing_for_fixpt_tool')
                    % DataStores already added.  If analyzing for fixpt
                    % need to set the storage class for referenced
                    % simulink signal vars.  When Analyzing for fixpt 
                    % addInportsForDSRW does not insert any blocks, it just
                    % sets the storage class accordingly
                    obj.addInportsForDSRW;
                end

                if ~obj.IsModelSlicer
                    obj.setFixedStepSolver;
                end
                % Configure coverage of blocks that get inserted while generating SLDV
                % compatible harness
                sldvshareprivate('configSLDVCompatibleHarness', obj.OrigModelH, obj.ModelH);
                obj.fixSubsystemRelativeSettings;
                obj.copySFDebugSettings;
                obj.saveExtractedModel;
                if ~obj.Status
                    msg_id = 'Sldv:SubSysExtract:ErrExtSubSys';
                    msg = getString(message(msg_id));
                    obj.deriveSsError(msg, msg_id, blockH);
                elseif obj.ExtractionMode==0 
                    [solverChanged, msg] = ...
                        Sldv.SubSystemExtract.createForcessDiscreteMsg(obj.ModelH, obj.OrigModelH);
                    if solverChanged && ~obj.IsValid
                        sldvshareprivate('util_gen_warning_notrace', ...
                            'Sldv:SubSysExtract:ForceDiscrete', msg);                                   
                    end 
                end
            end
        end
    end
    
    varargout{1} = obj.Status;
    varargout{2} = obj.ModelH;
    varargout{3} = obj.ErrMsg;
end

% LocalWords:  UI notrace NoSupportAsynchTrigSampleTimeSubSystem
