function [ success ] = generateHelp( self )
%GENERATEHELP generates an m-file containing a description of the solver
%
% This file is part of the y2f project: http://github.com/embotech/y2f, 
% a project maintained by embotech under the MIT open-source license.
%
% (c) Gian Ulli and embotech AG, Zurich, Switzerland, 2013-2021.

success = 0;

% Get solver name from option
solverName = self.default_codeoptions.name;

% Create file
mFileID = fopen([solverName '.m'],'w');

% Write documentation
fprintf(mFileID, '%% %s - a fast optimizer generated by FORCESPRO through Y2F\n',solverName); % TODO interior point??

% More than one internal solver --> say that!
if self.numSolvers > 1
    fprintf(mFileID, '%%\n');
    fprintf(mFileID, '%%   %s was generated based on a separable problem.',solverName);
    fprintf(mFileID, '%%   Internally, %u separate solver are used.\n',self.numSolvers);
end

% Parameter description
fprintf(mFileID, '%%\n');
fprintf(mFileID, '%%   OUTPUT = %s(PARAMS) solves a multistage problem\n',solverName);
fprintf(mFileID, '%%   subject to the parameters supplied in a cell array with the following elements:\n');

for i=1:self.numParams
    if self.paramSizes(i,1) == 1 && self.paramSizes(i,2) == 1 % scalar parameter
        fprintf(mFileID, '%%       PARAMS{%u} is %s (a scalar)\n',i,self.paramNames{i});
    elseif self.paramSizes(i,1) == 1 % row vector
        fprintf(mFileID, '%%       PARAMS{%u} is %s (row vector of length %u)\n',i,self.paramNames{i},self.paramSizes(i,2));
    elseif self.paramSizes(i,2) == 1 % column vector
        fprintf(mFileID, '%%       PARAMS{%u} is %s (column vector of length %u)\n',i,self.paramNames{i},self.paramSizes(i,1));
    else
        fprintf(mFileID, '%%       PARAMS{%u} is %s (matrix of size [%u x %u])\n',i,self.paramNames{i},self.paramSizes(i,1),self.paramSizes(i,2));
    end
end

% Ouput description
fprintf(mFileID, '%%\n');
fprintf(mFileID, '%%   OUTPUT is a cell array containg the values of the last iteration of the solver where\n');

for i=1:numel(self.outputSize)
    if self.outputSize{i}(1) == 1 && self.outputSize{i}(2) == 1 % scalar output
        fprintf(mFileID, '%%       OUTPUT{%u} is %s (a scalar)\n',i,self.outputNames{i});
    elseif self.outputSize{i}(1) == 1 % row vector
        fprintf(mFileID, '%%       OUTPUT{%u} is %s (row vector of length %u)\n',i,self.outputNames{i},self.outputSize{i}(2));
    elseif self.outputSize{i}(2) == 1 % column vector
        fprintf(mFileID, '%%       OUTPUT{%u} is %s (column vector of length %u)\n',i,self.outputNames{i},self.outputSize{i}(1));
    else
        fprintf(mFileID, '%%       OUTPUT{%u} is %s (matrix of size [%u x %u])\n',i,self.outputNames{i},self.outputSize{i}(1),self.outputSize{i}(2));
    end
end

% Exitflag description
if self.numSolvers == 1
    fprintf(mFileID, '%%\n');
    fprintf(mFileID, '%%   [OUTPUT, EXITFLAG] = %s(PARAMS) returns additionally\n',solverName);
    fprintf(mFileID, '%%   the integer EXITFLAG indicating the state of the solution with \n');
    fprintf(mFileID, '%%       1 - OPTIMAL solution has been found (subject to desired accuracy)\n');
    fprintf(mFileID, '%%       0 - Timeout - maximum number of iterations reached\n');
    fprintf(mFileID, '%%      -7 - Method could not progress. Problem may be infeasible.\n');
    fprintf(mFileID, '%%    -100 - License error\n');
    fprintf(mFileID, '%%\n');
else
    fprintf(mFileID, '%%\n');
    fprintf(mFileID, '%%   [OUTPUT, EXITFLAGS] = %s(PARAMS) returns additionally\n',solverName);
    fprintf(mFileID, '%%   the integer row vector EXITFLAGS indicating the state of the solution\n');
    fprintf(mFileID, '%%   for the different solvers with \n');
    fprintf(mFileID, '%%       EXITFLAGS(i) = 1    - OPTIMAL solution has been found (subject to desired accuracy)\n');
    fprintf(mFileID, '%%       EXITFLAGS(i) = 0    - Timeout - maximum number of iterations reached\n');
    fprintf(mFileID, '%%       EXITFLAGS(i) = -7   - Method could not progress. Problem may be infeasible.\n');
    fprintf(mFileID, '%%       EXITFLAGS(i) = -100 - License error\n');
    fprintf(mFileID, '%%   for the i-th solver\n');
    fprintf(mFileID, '%%\n');
end

% Info fields description
if self.numSolvers == 1
    fprintf(mFileID, '%%   [OUTPUT, EXITFLAG, INFO] = %s(PARAMS) returns \n',solverName);
    fprintf(mFileID, '%%   additional information about the last iterate:\n');
    fprintf(mFileID, '%%       INFO.it        - number of iterations that lead to this result\n');
    fprintf(mFileID, '%%       INFO.res_eq    - max. equality constraint residual\n');
    fprintf(mFileID, '%%       INFO.res_ineq  - max. inequality constraint residual\n');
    fprintf(mFileID, '%%       INFO.pobj      - primal objective\n');
    fprintf(mFileID, '%%       INFO.dobj      - dual objective\n');
    fprintf(mFileID, '%%       INFO.dgap      - duality gap := pobj - dobj\n');
    fprintf(mFileID, '%%       INFO.rdgap     - relative duality gap := |dgap / pobj|\n');
    fprintf(mFileID, '%%       INFO.mu        - duality measure\n');
    fprintf(mFileID, '%%       INFO.sigma     - centering parameter\n');
    fprintf(mFileID, '%%       INFO.lsit_aff  - iterations of affine line search\n');
    fprintf(mFileID, '%%       INFO.lsit_cc   - iterations of line search (combined direction)\n');
    fprintf(mFileID, '%%       INFO.step_aff  - step size (affine direction)\n');
    fprintf(mFileID, '%%       INFO.step_cc   - step size (centering direction)\n');
    fprintf(mFileID, '%%       INFO.solvetime - Time needed for solve (wall clock time)\n');
    fprintf(mFileID, '%%\n');
else
    fprintf(mFileID, '%%   [OUTPUT, EXITFLAGS, INFO] = %s(PARAMS) returns \n',solverName);
    fprintf(mFileID, '%%   additional information about the last iterate of the i-th solver:\n');
    fprintf(mFileID, '%%       INFO(i).it        - number of iterations that lead to this result\n');
    fprintf(mFileID, '%%       INFO(i).res_eq    - max. equality constraint residual\n');
    fprintf(mFileID, '%%       INFO(i).res_ineq  - max. inequality constraint residual\n');
    fprintf(mFileID, '%%       INFO(i).pobj      - primal objective\n');
    fprintf(mFileID, '%%       INFO(i).dobj      - dual objective\n');
    fprintf(mFileID, '%%       INFO(i).dgap      - duality gap := pobj - dobj\n');
    fprintf(mFileID, '%%       INFO(i).rdgap     - relative duality gap := |dgap / pobj|\n');
    fprintf(mFileID, '%%       INFO(i).mu        - duality measure\n');
    fprintf(mFileID, '%%       INFO(i).sigma     - centering parameter\n');
    fprintf(mFileID, '%%       INFO(i).lsit_aff  - iterations of affine line search\n');
    fprintf(mFileID, '%%       INFO(i).lsit_cc   - iterations of line search (combined direction)\n');
    fprintf(mFileID, '%%       INFO(i).step_aff  - step size (affine direction)\n');
    fprintf(mFileID, '%%       INFO(i).step_cc   - step size (centering direction)\n');
    fprintf(mFileID, '%%       INFO(i).solvetime - Time needed for solve (wall clock time)\n');
    fprintf(mFileID, '%%\n');
end

fprintf(mFileID, '%% See also COPYING');

% Close file
fclose(mFileID);

success = 1;

end
