function jsonString = masterAutoTab()
% MASTERAUTOTAB  Generates the complete .json file for tab completion
%   The file takes the solvers from allSolvers.m to produce a .json file 
%   like resources/functionSignatures.json. The file autoTab.m is used to generate
%   a single entry.

%   Copyright 2017-2019 The MathWorks, Inc.

% List of solvers
solvers = optim.internal.allSolvers;

% Convert data into json format
values = cell(1,length(solvers));
for i=1:length(solvers)
    [~,jsonString] = optim.internal.autoTab(char(solvers(i)));
    values{i} = insertAfter(jsonString(2:end-1),'"},',newline);
end

jsonString = ['{', newline, strjoin(values,[',' newline]), ',', newline];

% Minor formatting: add newlines to break up calls
jsonString = insertAfter(jsonString,'"optimoptions":{', newline);
jsonString = insertAfter(jsonString,'"inputs":[', newline);
jsonString = insertBefore(jsonString,'{"name":', '\t');

% Add json string for resetoptions
% NOTE: optim.options.SingleAlgorithm is not here since it lives in
% toolbox/MATLAB/optimfun. Therefore, we do not have to update it's JSON
% file when the shared/optimlib JSON file is changed.
% Leaving the loop here in case we introduce another in the future.
resetSolvers = {'optim.options.MultiAlgorithm'};
values = cell(1,length(resetSolvers));
for i = 1:length(resetSolvers)
    jsonResetString = autoTabResetoptions(resetSolvers{i});
    values{i} = insertAfter(jsonResetString,'"},',newline);
end
jsonResetString = [strjoin(values,[',' newline]), newline];
jsonString = [jsonString, jsonResetString, '}'];

% Write to file
fileLoc = fullfile(matlabroot,'toolbox', 'shared', 'optimlib', 'resources', 'functionSignatures.json');
fileID = fopen(fileLoc,'w');
fprintf(fileID,jsonString);
fclose(fileID);

%--------------------------------------------------------------------------
function jsonString = autoTabResetoptions(classAlgName)

% Append json string for the resetoptions entry
jsonResetoptionsStruct(1).name = "solveroptions";
jsonResetoptionsStruct(1).kind = "required";
jsonResetoptionsStruct(1).type = {classAlgName};
jsonResetoptionsStruct(2).name = "optionnames";
jsonResetoptionsStruct(2).kind = "required";
jsonResetoptionsStruct(2).type = {{"choices=properties(solveroptions)"}, {"cellstr"}}; %#ok
jsonResetoptionsString = jsonencode(...
    struct('resetoptions', ...
    struct('inputs',jsonResetoptionsStruct)));
jsonResetoptionsString = strrep(jsonResetoptionsString, 'resetoptions', ...
    [classAlgName, '.resetoptions']);
jsonString = jsonResetoptionsString(2:end-1);
jsonString = insertAfter(jsonString,'resetoptions":{', newline);
jsonString = insertAfter(jsonString,'"inputs":[', newline);
jsonString = insertBefore(jsonString,'{"name":', '\t');