function out = saveFminconSolution(x,optimValues,state,tracker_id,constraintTolerance, ... 
    verbosity,varargin)

% SAVEFMINCONSOLUTIONS saves best feasible solution (to be retrievd later)
% This function only considers feasibility into account when comparing
% solutions. At the end of the optimization, this function is called
% with a special syntax to retrieve the best feasible solution. At this 
% time, the stored solution is discarded (to clear insync persistent storage)
%
% Private to fmincon function. This function assumes that that optimValues
% have 'constrviolation' 'fval' fields and also assumes them to be
% non-empty and scalar.

%   Copyright 2020 The MathWorks, Inc.

% An array of struct to store best feasible solution from fmincon. An array
% is used to account for any potential nested usage of fmincon.
persistent solution

if nargin == 0
    % Initialize a tracker and return the index of the tracker to the
    % caller.
    aStruct = struct('x',[], ...
            'fval',Inf, ...
            'constrviolation',Inf, ...
            'firstorderopt',Inf, ...
            'insync',true);
    if ~isempty(solution)
        tracker_id = length(solution) + 1;
        solution(tracker_id) = aStruct;
    else
        tracker_id = 1;
        solution = aStruct;
    end
    out = tracker_id;
    return
end

if nargin == 1
    % Syntax to get the solution stored as persistent.
    tracker_id = x;
    out = solution(tracker_id);
    if nargout == 0
        solution(tracker_id) = []; % Remove the tracker
    end
    return;
end

out = false;
% If fmincon have a feasible solution and fval is better than the
% 'solution(tracker_id)' stored, update the 'solution(tracker_id)'
if optimValues.constrviolation <= constraintTolerance && ...
   optimValues.fval <= solution(tracker_id).fval
        solution(tracker_id).x = x;
        solution(tracker_id).fval = optimValues.fval;
        solution(tracker_id).constrviolation = optimValues.constrviolation;
        solution(tracker_id).firstorderopt = optimValues.firstorderopt;
        solution(tracker_id).insync = true;
else % Mark the solution to be 
    solution(tracker_id).insync = false;
end
   
if strcmpi(state,'done')
    if verbosity > 0 && ~isempty(solution) && ... 
       ~isempty(solution(tracker_id).x) && ~solution(tracker_id).insync
       messageData = {{'optimlib:commonMsgs:FeasiblePointOutputStruct'}, ...
                           {},true,false};
       createExitMsg(messageData{:});
    end
    
end
