class WorkflowActionBBTasks {

    public void rollbackExecutionPath(DelegateExecution execution) {
        final String action = (String) execution.getVariable(G_ACTION);
        final String resourceName = (String) execution.getVariable("resourceName");
        if (!(boolean) execution.getVariable("isRollback")) {
            List<ExecuteBuildingBlock> flowsToExecute =
                    (List<ExecuteBuildingBlock>) execution.getVariable("flowsToExecute");

            List<ExecuteBuildingBlock> flowsToExecuteChangeBBs = flowsToExecute.stream()
                    .filter(buildingBlock -> buildingBlock.getBuildingBlock().getBpmnFlowName().startsWith("Change"))
                    .collect(Collectors.toList());

            List<ExecuteBuildingBlock> rollbackFlows = new ArrayList<>();
            int currentSequence = (int) execution.getVariable(G_CURRENT_SEQUENCE);
            int listSize = flowsToExecute.size();

            for (int i = listSize - 1; i >= 0; i--) {
                if (i > currentSequence - 1) {
                    flowsToExecute.remove(i);
                } else {
                    String flowName = flowsToExecute.get(i).getBuildingBlock().getBpmnFlowName();
                    if (flowName.startsWith("Assign")) {
                        flowName = flowName.replaceFirst("Assign", "Unassign");
                    } else if (flowName.startsWith("Create")) {
                        flowName = flowName.replaceFirst("Create", "Delete");
                    } else if (flowName.startsWith("Activate")) {
                        flowName = flowName.replaceFirst("Activate", "Deactivate");
                    } else if (flowName.startsWith("Add")) {
                        flowName = flowName.replaceFirst("Add", "Delete");
                    } else if (flowName.startsWith("VNF")) {
                        if (flowName.startsWith("VNFSet")) {
                            flowName = flowName.replaceFirst("VNFSet", "VNFUnset");
                        } else if (flowName.startsWith("VNFLock")) {
                            flowName = flowName.replaceFirst("VNFLock", "VNFUnlock");
                        } else if (flowName.startsWith("VNFStop")) {
                            flowName = flowName.replaceFirst("VNFStop", "VNFStart");
                        } else if (flowName.startsWith("VNFQuiesce")) {
                            flowName = flowName.replaceFirst("VNFQuiesce", "VNFResume");
                        } else {
                            continue;
                        }
                    } else {
                        continue;
                    }
                    flowsToExecute.get(i).getBuildingBlock().setBpmnFlowName(flowName);
                    rollbackFlows.add(flowsToExecute.get(i));
                }
            }

            String handlingCode = (String) execution.getVariable(HANDLINGCODE);
            List<ExecuteBuildingBlock> rollbackFlowsFiltered = new ArrayList<>(rollbackFlows);
            if ("RollbackToAssigned".equals(handlingCode) || ROLLBACKTOCREATED.equals(handlingCode)) {
                for (ExecuteBuildingBlock rollbackFlow : rollbackFlows) {
                    if (rollbackFlow.getBuildingBlock().getBpmnFlowName().contains("Unassign")
                            && !rollbackFlow.getBuildingBlock().getBpmnFlowName().contains("FabricConfiguration")) {
                        rollbackFlowsFiltered.remove(rollbackFlow);
                    } else if (rollbackFlow.getBuildingBlock().getBpmnFlowName().contains("Delete")
                            && !rollbackFlow.getBuildingBlock().getBpmnFlowName().contains("FabricConfiguration")
                            && ROLLBACKTOCREATED.equals(handlingCode)) {
                        rollbackFlowsFiltered.remove(rollbackFlow);
                    }
                }
            }

            List<ExecuteBuildingBlock> rollbackFlowsFilteredNonChangeBBs = new ArrayList<>();
            if (action.equals(REPLACEINSTANCE) && resourceName.equals(VFMODULE)) {
                for (ExecuteBuildingBlock executeBuildingBlock : rollbackFlowsFiltered) {
                    if (!executeBuildingBlock.getBuildingBlock().getBpmnFlowName().startsWith("Change")) {
                        rollbackFlowsFilteredNonChangeBBs.add(executeBuildingBlock);
                    }
                }
                rollbackFlowsFiltered.clear();
                rollbackFlowsFiltered.addAll(flowsToExecuteChangeBBs);
                rollbackFlowsFiltered.addAll(rollbackFlowsFilteredNonChangeBBs);
            }

            workflowActionBBFailure.updateRequestErrorStatusMessage(execution);
            execution.setVariable("isRollbackNeeded", !rollbackFlows.isEmpty());
            execution.setVariable("flowsToExecute", rollbackFlowsFiltered);
            execution.setVariable(HANDLINGCODE, "PreformingRollback");
            execution.setVariable("isRollback", true);
            execution.setVariable(G_CURRENT_SEQUENCE, 0);
            execution.setVariable(RETRY_COUNT, 0);
        } else {
            workflowAction.buildAndThrowException(execution,
                    "Rollback has already been called. Cannot rollback a request that is currently in the rollback state.");
        }
    }

}