package io.github.theangrydev.businessflows;

import java.util.Optional;
import java.util.function.Function;

import static java.lang.String.format;

public class SadPath<Sad, Happy> extends BusinessFlowProjection<Sad, Happy> {

    SadPath(Sad sadPath, Happy happyPath, Exception technicalFailure) {
        super(sadPath, happyPath, technicalFailure);
    }

    public BusinessFlow<Sad, Happy> peek(Peek<Sad> peek) {
        return then(sad -> {
            peek.peek(sad);
            return BusinessFlow.sadPath(sad);
        });
    }

    public <NewSad> BusinessFlow<NewSad, Happy> then(Mapping<Sad, BusinessFlow<NewSad, Happy>> action) {
        return join(sad -> {
            try {
                return action.map(sad);
            } catch (Exception technicalFailure) {
                return BusinessFlow.technicalFailure(technicalFailure);
            }
        }, BusinessFlow::happyPath, BusinessFlow::technicalFailure);
    }

    //TODO: recovery to happy?

    public <NewSad> BusinessFlow<NewSad, Happy> map(Mapping<Sad, NewSad> mapping) {
        return then(mapping.andThen(BusinessFlow::sadPath));
    }

    public BusinessFlow<Sad, Happy> technicalFailure(Function<Sad, Exception> sadToTechnicalFailure) {
        return join(sadToTechnicalFailure.andThen(BusinessFlow::technicalFailure), BusinessFlow::happyPath, BusinessFlow::technicalFailure);
    }

    public Sad get() {
        return sadPath().orElseThrow(() -> new RuntimeException(format("Sad path not present. Happy path was '%s'. Exception was '%s'", happy, technicalFailure)));
    }

    private Optional<Sad> sadPath() {
        return Optional.ofNullable(sad);
    }
}

@@ -103,16 +103,90 @@
 ction;%0A%0A
+import static io.github.theangrydev.businessflows.BusinessFlow.happyPath;%0A
 import s
@@ -1022,34 +1022,143 @@
     
-//TODO: recovery to happy?
+public BusinessFlow%3CSad, Happy%3E recover(Mapping%3CSad, Happy%3E recovery) %7B%0A        return then(sad -%3E happyPath(recovery.map(sad)));%0A    %7D
 %0A%0A  

Add recovery for sad -> happy