package org.requirementsascode;

import java.io.Serializable;
import java.util.Optional;
import java.util.function.Predicate;

import org.requirementsascode.predicate.After;

/**
 * @author b_muth
 */
public abstract class FlowStep extends Step implements Serializable {
    private static final long serialVersionUID = -2926490717985964131L;

    private Flow flow;
    private Predicate<UseCaseModelRunner> flowPosition;

    private FlowStep previousStepInFlow;

    FlowStep(String stepName, UseCase useCase, Flow useCaseFlow) {
	super(stepName, useCase);
	this.flow = useCaseFlow;
    }

    public Flow getFlow() {
	return flow;
    }

    public Optional<FlowStep> getPreviousStepInFlow() {
	return Optional.ofNullable(previousStepInFlow);
    }

    protected void setPreviousStepInFlow(FlowStep previousStepInFlow) {
	this.previousStepInFlow = previousStepInFlow;
	setFlowPosition(new After(previousStepInFlow));
    }

    void setFlowPosition(Predicate<UseCaseModelRunner> flowPosition) {
	this.flowPosition = flowPosition;
    }

    public Optional<Predicate<UseCaseModelRunner>> getFlowPosition() {
	return Optional.ofNullable(flowPosition);
    }

    public void includeUseCase(UseCase includedUseCase) {
	for (Flow includedFlow : includedUseCase.getFlows()) {
	    includeFlow(includedFlow);
	}
    }

    private void includeFlow(Flow includedFlow) {
	Optional<FlowStep> optionalFirstStepOfIncludedFlow = includedFlow.getFirstStep();
	optionalFirstStepOfIncludedFlow.ifPresent(this::includeStep);
    }

    private void includeStep(FlowStep firstStepOfIncludedFlow) {
	Predicate<UseCaseModelRunner> originalFlowPosition = firstStepOfIncludedFlow.getFlowPosition()
		.orElse(r -> false);
	Predicate<UseCaseModelRunner> newFlowPosition = new After(this).or(originalFlowPosition);
	firstStepOfIncludedFlow.setFlowPosition(newFlowPosition);
    }
}

@@ -1494,27 +1494,57 @@
 t(this::
-i
+afterThisStepComesFirstStepOfI
 nclude
-Step
+dFlow
 );%0A    %7D
@@ -1566,19 +1566,49 @@
 oid 
-i
+afterThisStepComesFirstStepOfI
 nclude
-Step
+dFlow
 (Flo
@@ -1671,24 +1671,35 @@
 Runner%3E 
-original
+firstStepOfIncluded
 FlowPosi
@@ -1842,16 +1842,27 @@
 .or(
-original
+firstStepOfIncluded
 Flow

Improve naming