/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * license agreements; and to You under the Apache License, version 2.0:
 *
 *   https://www.apache.org/licenses/LICENSE-2.0
 *
 * This file is part of the Apache Pekko project, which was derived from Akka.
 */

/*
 * Copyright (C) 2015-2022 Lightbend Inc. <https://www.lightbend.com>
 */

package org.apache.pekko.stream

import org.apache.pekko.japi.{ function => japi }

object Supervision {
  sealed trait Directive

  /**
   * Scala API: The stream will be completed with failure if application code for processing an element
   * throws an exception.
   */
  case object Stop extends Directive

  /**
   * Java API: The stream will be completed with failure if application code for processing an element
   * throws an exception.
   */
  def stop = Stop

  /**
   * Scala API: The element is dropped and the stream continues if application code for processing
   * an element throws an exception.
   */
  case object Resume extends Directive

  /**
   * Java API: The element is dropped and the stream continues if application code for processing
   * an element throws an exception.
   */
  def resume = Resume

  /**
   * Scala API: The element is dropped and the stream continues after restarting the operator
   * if application code for processing an element throws an exception.
   * Restarting an operator means that any accumulated state is cleared. This is typically
   * performed by creating a new instance of the operator.
   */
  case object Restart extends Directive

  /**
   * Java API: The element is dropped and the stream continues after restarting the operator
   * if application code for processing an element throws an exception.
   * Restarting an operator means that any accumulated state is cleared. This is typically
   * performed by creating a new instance of the operator.
   */
  def restart = Restart

  type Decider = Function[Throwable, Directive]

  /**
   * Scala API: [[Decider]] that returns [[Stop]] for all exceptions.
   */
  val stoppingDecider: Decider with japi.Function[Throwable, Directive] =
    new Decider with japi.Function[Throwable, Directive] {
      override def apply(e: Throwable) = Stop
    }

  /**
   * Java API: Decider function that returns [[#stop]] for all exceptions.
   */
  val getStoppingDecider: japi.Function[Throwable, Directive] = stoppingDecider

  /**
   * Scala API: [[Decider]] that returns [[Resume]] for all exceptions.
   */
  val resumingDecider: Decider with japi.Function[Throwable, Directive] =
    new Decider with japi.Function[Throwable, Directive] {
      override def apply(e: Throwable) = Resume
    }

  /**
   * Java API: Decider function that returns [[#resume]] for all exceptions.
   */
  val getResumingDecider: japi.Function[Throwable, Directive] = resumingDecider

  /**
   * Scala API: [[Decider]] that returns [[Restart]] for all exceptions.
   */
  val restartingDecider: Decider with japi.Function[Throwable, Directive] =
    new Decider with japi.Function[Throwable, Directive] {
      override def apply(e: Throwable) = Restart
    }

  /**
   * Java API: Decider function that returns [[#restart]] for all exceptions.
   */
  val getRestartingDecider: japi.Function[Throwable, Directive] = restartingDecider

}
