/***********************************************************************/
/*                                                                     */
/*                      ADOBE CONFIDENTIAL                             */
/*                   _ _ _ _ _ _ _ _ _ _ _ _ _                         */
/*                                                                     */
/*  Copyright 2018 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.                                    */
/*                                                                     */
/***********************************************************************/

var SubProcessor = {};
SubProcessor.TYPE_SEQUENCE               = 'sequence';
SubProcessor.START                       = 'substep_start';
SubProcessor.SWITCH_SUBSTEP_NEXT         = 'substep_switch_next';
SubProcessor.SKIP_SUBSTEP                = 'substep_skip';
SubProcessor.FINISHED                    = 'subprocessing_finished';
SubProcessor.FINISHED_SUBSTEP_SUCCESS    = 'finished_substep_success';

SubProcessor.create = function(/*String*/ inType, /*Workflow*/ inWorkflow, /*Number*/ inStepIndex, /*WorkflowDisplayAdapter*/ inDisplay)
{
    var ret = null;

    if (inType == SubProcessor.TYPE_SEQUENCE)
    {
        ret = new SubProcessorSequential(inWorkflow, inStepIndex, inDisplay);
    }

    return ret;
}

function SubProcessorSequential(/*Workflow*/ inWorkflow, /*Number*/ inStepIndex, /*WorkflowDisplayAdapter*/ inDisplay)
{
    var thisObj = this;
    var workflow = inWorkflow;
    var parentStepIndex = inStepIndex;
    var display = inDisplay;

    var currentStep = NaN;
    var maxSteps = NaN;
    var triggerHandler = null;

    //////////////////////////////////////////////////////////////////////////////
    //
    // Is sub-processing running?
    //
    this.isStarted = function()
    {
        return !isNaN(currentStep);
    }

    //////////////////////////////////////////////////////////////////////////////
    //
    // Start sub-steps processing
    //
    this.start = function()
    {
        this.uninstallTrigger();

        currentStep = 0;
        maxSteps = getMaxSteps();

        if (isNaN(maxSteps) || maxSteps <= 0)
        {
            // invalid max sub-steps value
            throwlog("Invalid sub-step length");
        }

        var substep = getSubStep(currentStep);
        throwInvalid(substep, "WorkflowStep");

        substep.validatePreConditions(function()
        {
            // validation of pre conditions OK
            //
            display.showSubStepIndicator(parentStepIndex, currentStep);
            thisObj.installTrigger(substep);
        },
        function()
        {
            // validation of pre conditions FAILED
            //
            displayContent();

            gBroadcaster.sendMessage(SubProcessor.SKIP_SUBSTEP);
        });
    }

    //////////////////////////////////////////////////////////////////////////////
    //
    // Run next sub-step
    //
    this.nextSubStep = function()
    {
        this.uninstallTrigger();

        currentStep++;

        if (currentStep >= maxSteps)
        {
            // sub-processing finished, all sub-steps accomplished
            gBroadcaster.sendMessage(SubProcessor.FINISHED);
        }
        else
        {
            var substep = getSubStep(currentStep);
            throwInvalid(substep, "WorkflowStep");

            substep.validatePreConditions(function ()
            {
                // validation of pre conditions OK
                //
                display.showSubStepIndicator(parentStepIndex, currentStep);
                thisObj.installTrigger(substep);
            },
            function ()
            {
                // validation of pre conditions FAILED
                //
                displayContent();

                gBroadcaster.sendMessage(SubProcessor.SKIP_SUBSTEP);
            });
        }
    }

    //////////////////////////////////////////////////////////////////////////////
    //
    // Cancel sub-steps processing
    //
    this.cancel = function()
    {
        this.uninstallTrigger();
        currentStep = NaN;
    }

    //////////////////////////////////////////////////////////////////////////////
    //
    // Install trigger for current sub-step
    //
    this.installTrigger = function(/*WorkflowStep*/ inSubStep)
    {
        if (isValidProperty(inSubStep))
        {
            var triggers = inSubStep.getTriggers();

            if (isValidProperty(triggers) && triggers.length > 0)
            {
                try
                {
                    var subprocessor = this;
                    triggerHandler = new WorkflowTriggerHandler(triggers, function(/*[String]*/inReason, /*WorkflowTriggerValidationStatus*/ inStatus)
                    {
                        thisObj.onTrigger(inReason, inStatus);
                    });

                    triggerHandler.installHandler();
                }
                catch(exc)
                {
                    exclog(exc);
                    triggerHandler = null;
                }
            }
        }
    }

    //////////////////////////////////////////////////////////////////////////////
    //
    // Uninstall trigger for current sub-step
    //
    this.uninstallTrigger = function()
    {
        // clear event objects
        var job = new ScriptJob('clearEvents();');
        job.wait(null, function(/*String*/ inError)
        {
            dbglogError(inError);
        });

        if (isValidProperty(triggerHandler))
        {
            triggerHandler.uninstallHandler();
            triggerHandler = null;
        }
    }

    //////////////////////////////////////////////////////////////////////////////
    //
    // Trigger handler callback function
    //
    this.onTrigger = function(/*String*/ inReason, /*WorkflowTriggerValidationStatus*/ inStatus)
    {
        switch (inReason)
        {
            case WorkflowProcessor.FINISHED_STEP_SUCCESS:
            {
                this.uninstallTrigger();

                // Display content of current sub-step
                // (the content of a sub-step is displayed AFTER ti succeeded)
                //
                displayContent();

                gBroadcaster.sendMessage(SubProcessor.FINISHED_SUBSTEP_SUCCESS);
            }
            break;

            case WorkflowProcessor.FINISHED_FAILURE:
            {
                // restart trigger handler for the current sub-step
                //
                this.uninstallTrigger();

                var substep = getSubStep(currentStep);
                throwInvalid(substep, "WorkflowStep");

                thisObj.installTrigger(substep);
            }
            break;
        }
    }

    // ----------------------------------------------------

    function displayContent()
    {
        try
        {
            display.showSubStep(parentStepIndex, currentStep);
        }
        catch (exc)
        {
            exclog(exc);
        }
    }

    function getMaxSteps()
    {
        var ret = 0;

        var step = workflow.getStep(parentStepIndex);

        if (isValidProperty(step))
        {
            ret = step.getSubStepLength();
        }

        return ret;
    }

    function getSubStep(/*Number*/ inSubStepIndex)
    {
        var substep = null;
        var step = workflow.getStep(parentStepIndex);

        if (isValidProperty(step))
        {
            substep = step.getSubStep(inSubStepIndex);
        }

        return substep;
    }
}