function distcomp_evaluate_filetask(varargin)

% Copyright 2005-2015 The MathWorks, Inc.

try
    mdceDebug = getenv( 'MDCE_DEBUG' );
    % Debugging is enabled if MDCE_DEBUG is defined and set to anything
    % other than 'false'
    mdceDebugEnabled = ~isempty(mdceDebug) && ~strcmpi(mdceDebug, 'false');

    if mdceDebugEnabled
        mdceDebugLevel = str2double(mdceDebug);
        if ~isnan(mdceDebugLevel) && any(mdceDebugLevel == [0 1 2 3 4 5 6])
            logLevel = mdceDebugLevel;
        else
            LOG_LEVEL_ALL = 6;
            logLevel = LOG_LEVEL_ALL;
        end
    else
        % Log only level 0 messages if MDCE_DEBUG isn't defined or is 'false' - this can be
        % overridden in the decode function below or by defining this
        % variable. 
        LOG_LEVEL_SEVERE = 0;
        logLevel = LOG_LEVEL_SEVERE;
    end
    setSchedulerMessageHandler(iMessageHandler(logLevel));

    syncTaskEvaluation = getenv('MDCE_SYNCHRONOUS_TASK_EVALUATION');
    % Synchronous task evaluation is enabled if MDCE_SYNCHRONOUS_TASK_EVALUATION 
    % is defined and is set to true
    useSyncEvaluation = ~isempty(syncTaskEvaluation) && strcmpi(syncTaskEvaluation, 'true');

    % Initialize MatlabRefStore
    com.mathworks.toolbox.distcomp.util.MatlabRefStore.initMatlabRef();

    % If this a deployed (local) worker then we need to tell the deployed 
    % application not to simply exit when distcomp_evaluate_filetask returns - 
    % if the task is part of a parallel pool then the worker needs to remain
    % alive after this function returns
    iPreventDeployedWorkerExiting();

    if useSyncEvaluation
        % TODO: This is a workaround for a problem with SOA jobs. See g846800 and g846801.
        dctSchedulerMessage(6, 'Using synchronous task evaluation: calling distcomp_evaluate_filetask_core directly');
        % distcomp_evaluate_filetask_core expects an outputWriterStack.
        outputWriterStack = com.mathworks.toolbox.distcomp.cwo.WriterStack();
        distcomp_evaluate_filetask_core(outputWriterStack, mdceDebugEnabled, useSyncEvaluation, varargin{:});
    else
        dctSchedulerMessage(4, 'About to evaluate task with DistcompEvaluateFileTask');
        argsForTaskEvaluation = [useSyncEvaluation, varargin];
        % This serializes the arguments, and uses the MVM feval to call
        % distcomp_evaluate_filetask_core.
        e = com.mathworks.toolbox.distcomp.cwo.DistcompEvaluateFileTask;
        e.evaluate(mdceDebugEnabled, argsForTaskEvaluation);
    end
catch err
    dctSchedulerMessage(0, ['Evaluating task with DistcompEvaluateFileTask failed, the error was: ' err.getReport]);
    iAllowDeployedWorkerToExit();
    exitOnException(1);
end
end

%--------------------------------------------------------------------------
%
%--------------------------------------------------------------------------
function handler = iMessageHandler(desiredLevel)

loglvl = com.mathworks.toolbox.parallel.pctutil.logging.DistcompLevel.getLevelFromValue(desiredLevel);
LOGGER = com.mathworks.toolbox.parallel.pctutil.logging.RootLog.LOG;
LOGGER.setLevel(loglvl);

handler = @nHandler;

    function nHandler(msg, messageLevel)    
    
    if messageLevel > desiredLevel
        return;
    end    
    
    % This handler puts messages to two places - stdout (via fprintf)
    fprintf('%s | %s\n', datestr(now, 31), msg)
    
    % And to the java logger
    level = com.mathworks.toolbox.parallel.pctutil.logging.DistcompLevel.getLevelFromValue(messageLevel);
    LOGGER.log(level, ['MATLAB: ', msg]);
    end
end

%--------------------------------------------------------------------------
%
%--------------------------------------------------------------------------
function iPreventDeployedWorkerExiting()
% If this is a parallel pool job then we need the deployed worker process
% to remain alive after distcomp_evaluate_filetask returns - the default behaviour
% is for a deployed application to exit when the main function returns.
if isdeployed
    parallel.internal.cluster.workerShutdown('prevent');
end
end

%--------------------------------------------------------------------------
%
%--------------------------------------------------------------------------
function iAllowDeployedWorkerToExit()
% Allow the deployed worker to exit. 
% If this was a parallel pool job this means the worker process can now exit. If 
% it was a normal job then the worker process will exit when 
% distcomp_evaluate_filetask returns.
if isdeployed
    parallel.internal.cluster.workerShutdown('allow');
end
end
