function writeBatchFile(h,buildInfo,executor,wrapperFile)
%

%   Copyright 2014-2020 The MathWorks, Inc.

% Generate batch file content
content = '';

% Shell setup
if ~isVerboseBuild(h.BuilderBuildLogger)
    content = sprintf('%s\n', '@echo off');
end

for i = 1:numel( h.ToolchainInfo.ShellSetup )
    setupStr = strrep( h.ToolchainInfo.ShellSetup{ i }, '|>MATLAB_ROOT<|', matlabroot );
    setupStr = locCheckForSpecialMSVCVersion(h,setupStr);
    content = sprintf( '%s\n%s\n', content, setupStr );
end
% ---------------------------------------------------------
% Write out any build hook environment commands
% ---------------------------------------------------------
if ispc && ~isempty( h.BuildOpts.buildHookEnvVars )
    cmds = coder.make.internal.getPCBuildEnvironmentCmds...
           (h.BuildOpts.buildHookEnvVars, h.BuildOpts.buildHookPathPrepends);
    if ~isempty(cmds)
        content = sprintf('%s\n%s', content, cmds);
    end
end
% --------------------------
% Write the make command
% --------------------------
[mapMLR, forceMap, mlrToUse] = coder.make.internal.checkMLRDriveMap(buildInfo);
  
if mapMLR
    cmd = coder.make.internal.getMLRDriveMapCmd(mlrToUse, forceMap);
    content = sprintf('%s\n\n%s', content, cmd);
    
end

branchToErrorFcn = true;  % TODO: how do we set this? This is toolchain-specific.
% Clear the error level just before the make call (any successful command
% will do it), so that we only show the make errorlevel.
content = sprintf('%s\n%s\n', content, 'cd .');

% gmake fails when the terminal is using the 850 codepage and the makefile is written in 
% windows-1252. This case is widespread enough to warrant this fix:
% Change the terminal's codepage to 1252 before calling gmake
% See g2022294
localeInfo = feature('locale');
if ispc && strcmp(localeInfo.terminalEncoding, 'IBM850') && ...
        strcmp(localeInfo.encoding, 'windows-1252')
    content = sprintf('%s\n%s\n', content, 'chcp 1252');
end
% Write the make call
% Ignore the default command.
content = sprintf('%s\nif "%%1"=="" (%s) else (%s %%1)', ...
                  content, ...
                  [executor.Command.make, ' all'], ...
                  executor.Command.make);
% ---------------------------------------------------
% Write shell diagnostic code
% TODO: For LCC & default, this part is not written
% ---------------------------------------------------
if branchToErrorFcn
    % The program nmake.exe does not print an error message to stdout in certain
    % circumstances, so here we make sure that some printed manifestation of an
    % error will be emitted if an error occurs.  In particular, nmake prints no
    % error message if a DLL cannot be found since this error is reported by a
    % Windows system dialog that appears who knows where.
    % Note that the way errorlevel works in MS-DOS is that if the error level is
    % greater than or equal to the error level checked, it evaluates to true.  So
    % the statement 'if errorlevel 1...' will return true if any error has
    % occurred.
    % This statement used to be 'if not errorlevel 0...' which always evaluates
    % to false, because 'errorlevel 0' is always true (errorlevel is greater
    % than or equal to 0).
    content = sprintf('%s\n%s\n', content, '@if errorlevel 1 goto error_exit');
end
% Exit
content = sprintf('%s\n%s\n', content, 'exit /B 0');
% Define error subfunction
if branchToErrorFcn
    % In order to get the batch file to report an error to
    % the caller, a bad call must be made as the LAST line
    % in the file.
    content = sprintf('%s\n%s\n%s\n%s', ...
                      content, ...
                      ':error_exit', ...
                      'echo The make command returned an error of %errorlevel%', ...
                      'exit /B 1');
end

if isfile(wrapperFile)
    fid = fopen(wrapperFile, 'rt');
    existingContent = fread(fid, [1 Inf], '*char');
    fclose(fid);
    isUpToDate = strcmp(content, existingContent);
else
    isUpToDate = false;
end

if ~isUpToDate

    [fid,msg] = fopen( wrapperFile, 'wt' );

    if (fid == -1)
        % this can happen if the user tried to build from a sharepoint site,
        % which has BAT files blocked by default.  Generally speaking, if we've
        % gotten this far, then the codegen was able to write many files here
        % already, so it is unlikely a root-level write permissions problem,
        % but rather specific to the bat file creation
        me = MException(message('RTW:buildProcess:batFileOpenFailed', ...
                                wrapperFile,...
                                pwd,...
                                msg));
        
        throw(me);
    end


    % Write out the content
    fprintf(fid, '%s', content);

    % Stop writing and close the file
    fclose( fid );

end

end

function setupStr = locCheckForSpecialMSVCVersion(h,setupStr)
switch h.ToolchainInfo.Alias{1}
    case 'Microsoft-14.0'
        % this could be the MSVC 14.0 toolset in a VS2017 installation
        comp = coder.make.internal.getMexCompInfoFromKey(h.ToolchainInfo.Alias{1});
        if ~isempty(regexp(comp.comp.Location,'Microsoft Visual Studio[\\/]shared','ignorecase')) ...
                && contains(setupStr, 'vcvarsall.bat', 'IgnoreCase', true)
            vcver = lower(comp.comp.ShortName);
            batFileName = ['setup_' vcver '.bat'];
            
            batFileStr = comp.comp.Details.SetEnv;
            
            if ~contains(setupStr, 'amd64',  'IgnoreCase', true)
                % when the toolchain is to cross-compile 32-bit binaries (g1585512)
                % remove '\amd64' from the paths in the 64-bit version batFileStr
                batFileStr = regexprep(batFileStr, '\\amd64', '');
                % replace '\x64' with '\x86' in the 64-bit version batFileStr
                batFileStr = regexprep(batFileStr, '\\x64', '\\x86');
                % replace 'mexw64' with 'mexw32' in the 64-bit version batFileStr
                batFileStr = regexprep(batFileStr, 'mexw64', 'mexw32');
            end

            fid = fopen(batFileName, 'w+');
            fprintf( fid, '%s', batFileStr );
            fclose( fid );
            setupStr = sprintf('call %s',batFileName);
        end
end
end
