function hSubmitCommunicatingJob(obj, job, jobSupport, jobSupportID)
% hSubmitCommunicatingJob - submit job for execution

% Copyright 2011-2019 The MathWorks, Inc.

import parallel.cluster.HPCServer
import parallel.internal.apishared.HPCServerUtils
import parallel.internal.apishared.WorkerCommand
import parallel.internal.cluster.CJSJobMethods
import parallel.internal.cluster.SubmissionChecks

obj.ensureLicenseNumberIsSetOrError();
SubmissionChecks.checkSimultaneousTasksBeforeSubmission(job);
maxW = SubmissionChecks.checkWorkerLimsForSimultaneousJob(obj, job);
CJSJobMethods.duplicateTasksOfSimultaneousJob(job, jobSupport, jobSupportID, maxW);
jobSupport.prepareJobForSubmission(job, jobSupportID);

[cNames,  cVals ] = obj.getClusterEnvVarsForJobSubmission();
[jsNames, jsVals] = jobSupport.getJobSubmissionEnvVars(jobSupportID);
[ijNames, ijVals] = iCommJobEnvVars();
allNames = [cNames(:); jsNames(:); ijNames(:)];
allVals  = [cVals(:);  jsVals(:);   ijVals(:)];
jobEnvironmentVariables = [allNames(:), allVals(:)];

logLocation = jobSupport.getCommJobLogFile(jobSupportID);
jobIsCommunicating = true;

[~, matlabExe, matlabArgs] = WorkerCommand.hpcServerCommand(obj.OperatingSystem, ...
    obj.ClusterMatlabRoot, obj.UseSOAJobSubmission, jobIsCommunicating);
cmdToRun = iGetMpiexecCommand(matlabExe, matlabArgs, allNames);

[username, password] = HPCServer.getDefaultUserCredentials();
% Ask the server connection to submit the job
[schedulerJobIDs, schedulerTaskIDs] = obj.ServerConnection.submitParallelJob(cmdToRun, ...
    job.NumWorkersRange, numel(job.Tasks), ...
    jobEnvironmentVariables, logLocation, ...
    username, password);

% Now store the returned values in the job scheduler data
% Parallel jobs never need to know the job name
schedulerJobName = '';
% Parallel jobs are never SOA jobs
isSOAJob = false;
% non-SOA jobs never have an additional job ID
schedulerAdditionalJobID = [];
matlabTaskIDs = cell2mat(get(job.Tasks, {'Id'}));

% Set SchedulerIDs
% As this is a parallel job, they each have an ID of <jobID>.1
taskSchedulerID = schedulerJobIDs + ".1";
schedulerIDs = repmat(taskSchedulerID, size(job.Tasks));
set(job.Tasks, 'SchedulerID', schedulerIDs);

% TODO:later remove this abomination.
logTaskIDToken = '';
[~, relLog] = jobSupport.getCommJobLogFile(jobSupportID);

schedulerData = distcomp.MicrosoftJobSchedulerData(obj.ClusterVersion, ...
    obj.ServerConnection.SchedulerVersion, obj.Host, ...
    isSOAJob, schedulerJobName, schedulerJobIDs(1), schedulerAdditionalJobID, ...
    schedulerTaskIDs, matlabTaskIDs, relLog, logTaskIDToken);
job.JobSchedulerData = schedulerData;
end

%----------------------------------------------------------
function [names, vals] = iCommJobEnvVars()
names = {'PARALLEL_SERVER_DECODE_FUNCTION', ...
         'MDCE_FORCE_MPI_OPTION'};
vals  = {'parallel.internal.decode.hpcserverParallelTask', ...
         'sys-msmpi'};
end

%----------------------------------------------------------
function cmd = iGetMpiexecCommand(matlabExe, matlabArgs, envNames)
matlabCommand = sprintf('"%s" %s', matlabExe,  matlabArgs);
hpcsEnvNames = {'CCP_NODES', 'CCP_JOBID'};
envNames = [envNames(:); hpcsEnvNames(:)];
% Build the genvlist portion
envList = sprintf('%s,', envNames{:});
envList = envList(1:end-1);
ccpHostsVar = '%CCP_NODES%';
cmd = sprintf('mpiexec -l -genvlist %s -hosts %s %s', envList, ccpHostsVar, matlabCommand);
end

