function status = slvnvmergeharness(varargin)
%SLVNVMERGEHARNESS - Merge test cases and initializations into a single model
%
%   SLVNVMERGEHARNESS(NAME, MODELS, INITCMDS) collects the test data 
%   and initialization commands from each test harness model listed in MODELS 
%   and saves them in model NAME. 
% 
%   If NAME does not exist, SLVNVMERGEHARNESS creates it as a copy of the
%   first model in MODELS. SLVNVMERGEHARNESS then merges data from other
%   models listed in MODELS into this model. If you create NAME from a
%   previous SLVNVMERGEHARNESS run, subsequent runs of this function for
%   NAME maintain the correct structure and initialization from the earlier
%   run. If NAME matches an existing Simulink model, SLVNVMERGEHARNESS
%   merges the test data from MODELS into NAME.
%
%   This function assumes that NAME and the rest of the models in the list
%   MODELS will have only one Signal Editor block on the top level. If a
%   model in MODELS doesn't meet this restriction or its top level Signal
%   Editor block doesn't have the same number of signals with the top
%   level Signal Editor block in NAME, then it will not be merged into
%   NAME.
%
%   An array of initialization commands INITCMDS defines parameter 
%   settings for the test cases in each model.  INITCMDS must be a cell array 
%   of strings the same length as MODELS.  The initialization command 
%   INITCMDS{I} is evaluated in the base workspace whenever a test case that 
%   originated in MODELS{I} is executed.
%
%
%   SLVNVMERGEHARNESS is especially convenient to use with SLDVGENCOV to combine
%   test cases using different sets of parameter values.
%  
%  
%   Examples:
%  
%   slvnvmergeharness('alltests',{'myharness','mymod_harness'},{'p1=1','p1=0'})
%  
%   Creates a new model "alltests", where the test input definition 
%   includes all the tests from mymod_harness and myharness.  At the start of
%   a simulation of "alltests" Simulink invokes the command "p1=1" for test 
%   cases originally in myharness and "p1=0" for test cases originally in
%   mymod_harness.
%  
%   slvnvmergeharness('mymod_harness','mymod_harness','p1=1')
%  
%   Create a test harness that invokes "p1=1" at the start of each simulation. 
%   It also configures the model so that other harness models can be merged
%   into this model.
%  
%   slvnvmergeharness('myharness','mymod_harness','load myparams.mat')
%  
%   Merges the test cases from mymod_harness into myharness.  It also configures 
%   the model to invoke "load myparams.mat" whenever a test case that 
%   originated in mymod_harness is invoked.
%
%   See also SLVNVMAKEHARNESS.

%   Copyright 2006-2017 The MathWorks, Inc.
%   
    narginchk(2, 3);
    
    name = convertStringsToChars(varargin{1});
    destModelH = [];
    if ischar(name)
        if exist(name, 'file')==4
            [destModelH,errMsg] = Sldv.loadIfNeeded(name);
            if ~isempty(errMsg)
                error(errMsg);
            end
        end
    else
        if ishandle(name)
            destModelH = name;
        else
            error(message('Slvnv:slvnvmergeharness:DestModel'));
        end
    end
    
    if ~isempty(destModelH)
        errMsg = Sldv.forceModelWritable(destModelH);
        if ~isempty(errMsg)
            error(errMsg);
        end
    end

    models = locParseArg(varargin{2});

    if nargin<3
        emptyCell = {''};
        initCmds = emptyCell(ones(length(models),1));
    else
        initCmds = locParseArg(varargin{3});
    end

    if length(initCmds)~=length(models)
        error(message('Slvnv:slvnvmergeharness:MisMatch'));
    end

    modelCnt = length(models);
    modelHs = zeros(1,modelCnt);
    
    if iscell(models)
        for idx=1:length(models)
            [modelHs(idx),errMsg] = Sldv.loadIfNeeded(models{idx}); 
            if ~isempty(errMsg)
                error(errMsg);
            end
        end
    else
        modelHs = models;
    end
    
    % get the model with the largest signal source. This should include all
    % signals to be merged across all models including the unused ones
    [~, idx] = Sldv.HarnessUtils.getModelWithLargestSignalSource(modelHs);
    modelHs([1, idx]) = modelHs([idx, 1]); % bring the model with largest signal source to top

    isNew = false;
    if isempty(destModelH)
        [destModelH, errMsg] = Sldv.copyModel(name, modelHs(1));
        if ~isempty(errMsg)
            if isa(errMsg, 'MException')
                rethrow(errMsg);
            else
                error(errMsg);
            end
        end
        isNew = true;
        
        % Extra step for RMI: may need to copy requirements
        harnessSource = Sldv.harnesssource.Source.getSource(modelHs(1));
        if isa(harnessSource,'Sldv.harnesssource.SignalBuilder')
            %Signal Builder tab links
            sigb1 = [get_param(modelHs(1),'Name') '/Inputs'];
            if rmi.objHasReqs(sigb1, [])     % do not filter by tags
                [~,~,~, grps] = signalbuilder(sigb1);   % we just need the group count
                for i = 1:length(grps)
                    reqs = rmi.getReqs(sigb1, i);
                    if ~isempty(reqs)
                        rmi.setReqs([name '/Inputs'], reqs, i);
                    end
                end
            end
        elseif isa(harnessSource,'Sldv.harnesssource.SignalEditor')
            %Signal Editor block does not have requirements on each group
            %like signal builder so no need for a for-loop
            sige1 = harnessSource.blockH;
            if rmi.objHasReqs(sige1, [])     % do not filter by tags
                reqs = rmi.getReqs(sige1);
                if ~isempty(reqs)
                    rmi.catReqs([name '/Inputs'], reqs);
                end
            end
        else
            %NO-OP
        end
        
        modelHs(1) = destModelH;
    end

    status = Sldv.HarnessUtils.merge(destModelH, modelHs, initCmds, isNew, mfilename);
    
function output = locParseArg(inputArgs)
    if iscell(inputArgs)
        [inputArgs{:}] = convertStringsToChars(inputArgs{:});
        output = inputArgs;
    else
        output = convertStringsToChars(inputArgs);
        if ischar(output)
            output = {output};
        end
    end


% LocalWords:  INITCMDS alltests myharness mymod myparams SLVNV Slvnv Dest Mis
