package com.airlock.iam.flow.api.domain.model.step;

import com.airlock.iam.flow.api.domain.model.tag.Tag;
import java.util.Arrays;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

public interface StepResult {
   StepResult.StepResultType type();

   Optional<StepAction> nextAction();

   Optional<StepError> error();

   boolean hasError(StepError var1);

   Set<Tag> obtainedTags();

   <T extends StepResultData> Optional<T> resultData();

   <T extends InternalStepResultData> Optional<T> internalResultData();

   Map<String, Object> metadata();

   AdditionalAttributes additionalAttributes();

   default boolean hasType(StepResult.StepResultType resultType) {
      return this.type() == resultType;
   }

   default boolean hasAnyType(StepResult.StepResultType... resultTypes) {
      return Arrays.stream(resultTypes).anyMatch(this::hasType);
   }

   default boolean isFailure() {
      return this.type().isFailure();
   }

   default boolean isLeavingStep() {
      return this.type().isLeavingStep();
   }

   default boolean isFinalFailure() {
      return this.type().isFinalFailure();
   }

   default boolean isReturningToClient() {
      return this.type().isReturningToClient();
   }

   default boolean isSuccess() {
      return this.hasType(StepResult.StepResultType.SUCCESS);
   }

   StepResultBuilder toBuilder();

   enum StepResultType {
      SUCCESS,
      STAY,
      SKIP,
      GOTO,
      FAIL,
      FAIL_RETRY,
      FAIL_GOTO,
      INTERNAL_ERROR,
      SUBFLOW_SELECTED;

      public boolean isFailure() {
         return this == FAIL || this == FAIL_RETRY || this == FAIL_GOTO || this == INTERNAL_ERROR;
      }

      public boolean isFinalFailure() {
         return this == FAIL || this == INTERNAL_ERROR;
      }

      public boolean isLeavingStep() {
         return this == SUCCESS || this == SKIP || this == GOTO || this == FAIL || this == FAIL_GOTO || this == INTERNAL_ERROR || this == SUBFLOW_SELECTED;
      }

      public boolean isReturningToClient() {
         return this == STAY || this == FAIL || this == FAIL_RETRY || this == INTERNAL_ERROR;
      }

      public boolean isGotoAction() {
         return this == GOTO || this == FAIL_GOTO;
      }

      public boolean canContainTags() {
         return this == SUCCESS || this == STAY || this == SUBFLOW_SELECTED;
      }
   }
}
