function [ok, sparams, eparams, errmsg] = loadParamsFile(file)
% Open file
% Read params struct

%   Copyright 2013-2021 The MathWorks, Inc.

    ok = true;
    sparams = [];
    eparams = [];
    errmsg = '';
    currPath = path;


    [ dir, name,ext ]  = fileparts(file);
    if ~isempty(dir)
        addpath(dir);
    end

    if ~exist(file, 'file') || ~strcmp(ext , '.m')
        ME = MException('MATLAB:UndefinedFunction', ...
                        'Not a function or script');
        throw(ME);
    end


    isfunction = true;
    funchandle = str2func(name);
    try
        nargout(funchandle);
    catch Mex %#ok<NASGU>
        isfunction = false;
    end

    try
        if isfunction
            params = feval(name);
        else
            currentvars = whos;
            currentvarnames = {currentvars.name};
            eval(name);
            newvars = whos;
            newvarnames = {newvars.name};
            [~,index] = setdiff(newvarnames, currentvarnames);
            paramsIsfound = false;
            for idx = 1:length(index)
                if strcmp(newvars(index(idx)).name,'params')
                    paramsIsfound = true;
                    break;
                end
            end
            if ~paramsIsfound
                params = {};
            end
        end

        % This file has multiple configurations, I am taking the first one.
        if length(params) > 1
            params = params(1);
        end


        flds = fieldnames(params);
        for i = 1:length(flds)
            [~, errId] = sldvshareprivate('checkSldvSpecification', params.(flds{i}));
            if isempty(errId)
                %following will convert the cell array of constraints to strings using the same
                %representation as in report generation. Here we print do
                %changes like Sldv.Interval(2, 3. '()') --> (2,3). This is
                %not supported as an input. hence we cannot do this
                %conversion while loading constraints from file. Instead I
                %have a local pretty print facility for doing this. When we
                %parse the input strings to support all such syntax we
                %should replace the pretty print utility with
                %util_mxarray_print to keep the representation in report
                %and here same.
                %sparams.(flds{i}) = sldvprivate('util_mxarray_print', spec);
                if slavteng('feature','BusParameterTuning') && isstruct(params.(flds{i}))
                    sparams.(flds{i}) = prettyprintStructSpec(params.(flds{i}));
                else
                    sparams.(flds{i}) = prettyprint(params.(flds{i}));
                end
            else
                ok = false;
                eparams.(flds{i}) = '';
            end
        end

    catch me
        ok = false; %#ok<NASGU>
        rethrow(me);
    end

    path(currPath);
end




function strspec = prettyprint(spec)
    if iscell(spec)
        strspec = '{';
        for i=1:length(spec)
            strspec = [ strspec printElem(spec{i})];             %#ok<AGROW>
            if i < length(spec)
                strspec = [strspec ', '];                 %#ok<AGROW>
            end
        end
        strspec = [strspec '}'];
    else
        strspec = printElem(spec);
    end
end

function returnSpec = prettyprintStructSpec(spec)
% Unlike prettyprint, prettyprintStructSpec returns a astructure whose
% fields are the fields of the structure 'spec' and values are string
% format of the specification mentioned
% So, it return a string if spec if a leaf specification. Else it
% returns a structured spec
    returnSpec = struct;
    if isstruct(spec)
        currentFields = fieldnames(spec);
        for idx = 1:length(currentFields)
            returnSpec.(currentFields{idx}) = prettyprintStructSpec(spec.(currentFields{idx}));
        end
    else
        returnSpec = prettyprint(spec);
    end
end


function elem = printElem(spec)
    if isa(spec,'Sldv.Point')
        elem = ['Sldv.Point(' printNum(spec.getFlatValue) ')'] ;
    elseif isa(spec,'Sldv.Interval')
        if isempty(spec.getBoundary)
            elem = ['Sldv.Interval(' printNum(spec.getFlatLow) ', ' printNum(spec.getFlatHigh) ')'];
        else
            elem = ['Sldv.Interval(' printNum(spec.getFlatLow) ', ' printNum(spec.getFlatHigh)  ', ' '''' spec.getBoundary ''''  ')'];
        end
    elseif isnumeric(spec) || islogical(spec)
        if isempty(spec)
            elem = '[]';
        elseif length(spec) == 1
            elem = printNum(spec);
        elseif (length(spec) == 2)
            elem = ['[' printNum(spec(1))  ', '  printNum(spec(2)) ']'];
        else
            error(message('Sldv:CheckSpec:Syntax'));
        end
    else
        error(message('Sldv:CheckSpec:Syntax'));
    end
end


function str = printNum(num)
    if isscalar (num)
        str = sldvshareprivate('util_num2str', num);
    else
        str = mat2str(num);
    end
end
