%% generate_preamble
%    generates the preamble for the eml code, the preamble is
%    everything before the first if statement, this is seperated
%    out to make the code simpler.
% inputs:
%   object:EMLGenerator - current object
% outputs:
%   code:string - string of eml code
% Author: Colin Eles elesc@mcmaster.ca
% Organization: McMaster Centre for Software Certification
function code = generate_preamble(object)

code = [];
function_name = EMLGenerator.parse_inputs(object.data.function_name);
%generate input list
inputs = ca.mcmaster.cas.tabularexpressiontoolbox.parsers.VariableParser(object.data.function_inputs);
parsed_input = inputs.getVarList();
input_iter = parsed_input.iterator()
input = [];
while input_iter.hasNext()
    var = input_iter.next()
    input = [input char(var.name())];
    if input_iter.hasNext()
        input = [input ','];
    end
end

output = [];
if (object.data.multi_mode == 1)
    for i=1:size(object.data.Grid1.cells,2)
        parsed_output = EMLGenerator.parse_inputs(strtrim(char(object.data.Grid1.cells(i).cond_text)));
        
        output = [output char(parsed_output{1}(1))];
        
        if i ~= size(object.data.Grid1.cells,2)
            output = [output ','];
        end
    end
else
    output = 'output';
end

exception_flag = object.data.settings.except;

if (exception_flag)
    code = sprintf('function [%s, exception] = %s(%s)\n%s\n',output,char(function_name{1}(1)),input,'%%#eml');    
else
    code = sprintf('function [%s] = %s(%s)\n%s\n',output,char(function_name{1}(1)),input,'%%#eml');
end





% simulink forces you to have an output for all execution paths
% since it can't compute completness and disjointness we need
% to have a default value, if the user builds the table
% properly the default value will never be used. since
% different types might have a different default value, the
% temporary solution is just to use one of the outputs from our
% table, we will use the first cell because it is
% guaranteed to
% be filled in, regardless of the dimensionality of the table.

left_top_right_top_cell = object.data.Grid2.cells(1);
while size(left_top_right_top_cell.subgrid) ~= 0
    left_top_right_top_cell = left_top_right_top_cell.subgrid.cells(1);
end


if (object.data.multi_mode == 1)
    for i=1:size(object.data.Grid1.cells,2)
        parsed_output = EMLGenerator.parse_inputs(strtrim(char(object.data.Grid1.cells(i).cond_text)));
        
        output_str = char(parsed_output{1}(1));

        code = [code sprintf('%s=%s;\n',output_str,EMLGenerator.type_convert(output_str,object.datatype,char(object.data.Grid0.search_return(object.data.Grid1.cells(i), left_top_right_top_cell).result_text)))];
        
    end
    
else
    test  = 'output';
    output_string = EMLGenerator.type_convert(test,object.datatype,char(object.data.Grid0.Cells(1).result_text) );
    code = [code sprintf('output=%s;\n', output_string )];
    
end


if (exception_flag)
    
    % generate NaN exceptions
    nan_string = '';
    
    % genereate constraint exception
    cons_string = '';

    for i = 1:size(parsed_input,2)
       % for each input consider if a NaN
       
       nan_string = [nan_string 'isnan(' char(parsed_input{i}(1)) ')'];
       
       if i ~= size(parsed_input,2)
            nan_string = [nan_string '||'];
       end
       
       if size(parsed_input{i},2) == 2
           
           str = regexp(parsed_input{i}(2),'(?<=\|).*(?=})','match','once');
           
           if (~isempty(char(str)))
                cons_string = [cons_string sprintf('if ~(%s) \n  exception = true;\n  return;\nelse\n  exception = false;\nend\n',char(str))];
           end
           
       end
       
       
       
    end
    code = [code sprintf('if (%s) \n  exception = true;\n  return;\nelse\n  exception = false;\nend\n',nan_string)];
        code = [code cons_string];
    
    
    
end

end

