%

% Copyright 2018-2019 The MathWorks, Inc.
function valueStruct = toValue(params, needsEval)
    if nargin == 1
        needsEval = true(numel(params), 1);
    end
    validateInputs(params, needsEval);
    workspace = {params.Workspace};
    valueStruct = struct('Name', {params.Name}, 'Value', [], ...
        'BlockPath', workspace);
    oc = cacheBaseWorkspaceVars; %#ok<NASGU>
    evalin('base', 'clearvars');
    maskIdx = xls.internal.SaveVariablesToScript.getMaskIdx(workspace)';
    needsEval = needsEval & ~maskIdx; % do not eval mask params
    valueStruct = getValues(valueStruct, params, needsEval);
end

function validateInputs(params, needsEval)
    assert(numel(params) == numel(needsEval));
    validateattributes(params,"Simulink.Simulation.Variable",{'column'});
    validateattributes(needsEval,"logical",{'column'});
end

function oc = cacheBaseWorkspaceVars
    % cache, clear, then restore base workspace variables
    vars = evalin('base', 'who');
    values = cellfun(@(var) evalin('base', var), vars, 'Uniform', false);
    oc = onCleanup(@() restoreVars(vars, values));
end

function restoreVars(vars, vals)
    cellfun(@(var, val) assignin('base', var, val), vars, vals);
end

function value = getCreatedVar(param, name)
    assert(isempty(evalin('base', 'who')));
    % must eval with no output arguments because format from
    % saveVariablesToScript contains 'var =' in string
    evalin('base', param.Value + ";");
    createdVar = evalin('base', 'who');
    if ~isscalar(createdVar)
        error(message('sl_xls:Parameter:MultipleVariables', string(name)));
    end
    value = evalin('base', createdVar{1});
    evalin('base', 'clearvars');
end

function valueStruct = getValues(valueStruct, params, needsEval)
    if any(needsEval)
        values = arrayfun(@getCreatedVar, params(needsEval)', ...
            {valueStruct(needsEval).Name}, 'Uniform', false);
        [valueStruct(needsEval).Value] = values{:};
    end

    [valueStruct(~needsEval).Value] = params(~needsEval).Value;
end
