function toMCode(hCodeTree,hText,options,isFirst)
% Generates code based on input codetree object

% Copyright 2006-2012 The MathWorks, Inc.

if nargin == 2
    isFirst = false;
    options.MFileName = '';
    options.OutputTopNode = true;
end

local_generate_function_header(hCodeTree,hText,options,isFirst);
hCodeTree.CodeRoot.toMCode(hText);
hCodeTree.CodeRoot.subFunctionsToMCode(hText,options,false);

%---------------------------------------------------------------------%
function local_generate_function_header(hCodeTree,hText,options,isFirst)
% Generate first line of code in the following form:
% function [h] = create<ObjectName> (<property_name>_in, ...)

% If this is not the first, add a separator:
if ~isFirst
    hText.addln('');
    hText.addln('%-------------------------------------------------------------------------%');
end

hVarTable = hCodeTree.VariableTable;

% Determine m-file name
if ~isFirst || isempty(options.MFileName)
    function_name = hCodeTree.String;
else
    name = options.MFileName;
    function_name = name;
end

% Generate output variable
output_variable = [];
if (options.OutputTopNode)
    % Loop through argument list and find first argument that is flagged
    % as an output variable
    hVarList = get(hVarTable,'VariableList');
    for n = 1:length(hVarList)
        hVar = hVarList(n);
        if get(hVar,'IsOutputArgument')  
            output_variable = get(hVar,'String');
        end
    end
    setRemovalPermissions(hVar,false);
end

% Add function name 
if (options.OutputTopNode) && ~isempty(output_variable)
    str = ['function [',output_variable,'] = ',function_name]; 
else 
    str = ['function ',function_name];
end

hText.addln(str);

% Get the number of input arguments
hVarList = get(hVarTable,'VariableList');

if ~isempty(hVarList)
    % Add input argument list to function declaration
    hInputVarList = hVarList(isFunctionInput(hVarList));
else
    hInputVarList = [];
end

hText.add(localGetArgumentList(hInputVarList));

% Standard H1 line
str = sprintf('%%%s',upper(function_name));
hText.addln(str);

% Add input variables to H1 line
hText.add((localGetArgumentList(hInputVarList)));

% Create comments for each input argument
for n = length(hInputVarList):-1:1
    hText.addln(['%  ', hInputVarList(n).getCommentString()]);
end

% If this is the first function in the file, add the internal comment.
if isFirst
    % Internal comment
    hText.addln(' ');
    currentDate = datestr(now);
    strAutogeneratedByMATLAB = getString(message('MATLAB:codetools:codegen:codetree:toMCode:AutogeneratedByMATLAB',currentDate));
    hText.addln(sprintf('%%  %s', strAutogeneratedByMATLAB));
    hText.addln(' ');
end


function str = localGetArgumentList(hVars)
% Conver the provided variables into a list of comma-separated strings,
% surrounded by brackets.
if isempty(hVars)
    str = '';
else
    VarStrs = get(hVars, {'String'});
    assert(~any(cellfun('isempty', VarStrs)),'MATLAB:codetools:codeargument:NoString', ...
            'codeargument String property is empty');
    
    str = sprintf('%s, ', VarStrs{end:-1:1});
    str = ['(' str(1:end-2) ')'];
end
