/***********************************************************************/
/*                                                                     */
/*                      ADOBE CONFIDENTIAL                             */
/*                   _ _ _ _ _ _ _ _ _ _ _ _ _                         */
/*                                                                     */
/*  Copyright 2016 Adobe Systems Incorporated                          */
/*  All Rights Reserved.                                               */
/*                                                                     */
/* NOTICE:  All information contained herein is, and remains           */
/* the property of Adobe Systems Incorporated and its suppliers,       */
/* if any.  The intellectual and technical concepts contained          */
/* herein are proprietary to Adobe Systems Incorporated and its        */
/* suppliers and are protected by all applicable intellectual property */
/* laws, including trade secret and copyright laws.                    */
/* Dissemination of this information or reproduction of this material  */
/* is strictly forbidden unless prior written permission is obtained   */
/* from Adobe Systems Incorporated.                                    */
/*                                                                     */
/***********************************************************************/

function SequenceJob(/*[Array]*/ inFunctions, /*[any ...]*/ inFirstFunctionArguments)
{
	throwInvalid(inFunctions);
	
	var status = IJob.STATUS_PENDING;
	var waiting = false;
	var functions = inFunctions;
	var sequenceArgs = [];
	var current = 0;
	var job = null;
	var successHandler = null;
	var errorHandler = null;
	
	//////////////////////////////////////////////////////////////////////////////
	//
	// Get Job result
	//
	this.getResult = function()
	{
        if (this.isStatus(IJob.STATUS_FINISHED | IJob.STATUS_SUCCESS) && 
        	!this.isStatus(IJob.STATUS_CANCELED) && isValidProperty(job))
        {
            return job.getResult();
        }

        return null;
	}

	//////////////////////////////////////////////////////////////////////////////
	//
	// Get Job error
	//
	this.getError = function()
	{
        if (this.isStatus(IJob.STATUS_FINISHED | IJob.STATUS_ERROR) && 
        	!this.isStatus(IJob.STATUS_CANCELED) && isValidProperty(job))
        {
            return job.getError();
        }

        return null;
	}

	//////////////////////////////////////////////////////////////////////////////
	//
	// Wait for Job completed
	//
	this.wait = function(/*[Function]*/ inSuccessFct, /*[Function]*/ inErrorFct)
	{
		if (!waiting && !this.isStatus(IJob.STATUS_CANCELED))
		{
			var thisObj = this;
			
			function onSuccess(/*[any]*/ inResult)
			{
				current++;

				if (current < functions.length)
				{
					try
					{
						job = functions[current](inResult);
						job.wait(onSuccess, onError);
					}
					catch(exc)
					{
						exclog(exc);
						throw exc;
					}
				}
				else
				{
					if (!thisObj.isStatus(IJob.STATUS_FINISHED))
					{
						status = IJob.STATUS_FINISHED | IJob.STATUS_SUCCESS;
					}

					if (isValidProperty(successHandler))
					{
						successHandler(inResult);
					}
				}
			}
	
			function onError(/*[any]*/ inError)
			{
				if (!thisObj.isStatus(IJob.STATUS_FINISHED))
				{
					status = IJob.STATUS_FINISHED | IJob.STATUS_ERROR;
				}

				if (isValidProperty(errorHandler))
				{
					errorHandler(inError);
				}
			}
				
			waiting = true;
			successHandler = inSuccessFct;
			errorHandler = inErrorFct;
			current = 0;
			
			try
			{
				job = functions[current].apply(null, sequenceArgs);
				job.wait(onSuccess, onError);
			}
			catch(exc)
			{
				exclog(exc);
				throw exc;
			}
		}
	}

	//////////////////////////////////////////////////////////////////////////////
	//
	// Cancel Job
	//
	this.cancel = function()
	{
        if (this.isStatus(IJob.STATUS_PENDING))
        {
            status = IJob.STATUS_CANCELED | IJob.STATUS_FINISHED;
            successHandler = null;
            errorHandler = null;
            
            if (isValidProperty(job))
            {
            	job.cancel();
            }
        }
	}

    //////////////////////////////////////////////////////////////////////////////
    //
    // Get Job status
    //
    this.getStatus = function()
    {
        return status;
    }

    //////////////////////////////////////////////////////////////////////////////
    //
    // Check Job status
    //
    this.isStatus = function(/*[Number]*/ inStatusFlags)
    {
        return ((status & inStatusFlags) == inStatusFlags);
    }

	// Initialization //////////////////////////////////////////////////////////////
		
	if (arguments.length > 1)
	{
		for (var i=1; i<arguments.length; i++)
		{
			sequenceArgs.push(arguments[i]);
		}
	}
}
