/**
 * @since 1.0.0
 */
import type { Effect } from "effect/Effect"
import * as Runtime from "effect/Runtime"

/**
 * @since 1.0.0
 * @category Run main
 */
export const runMain: {
  /**
   * @since 1.0.0
   * @category Run main
   */
  (
    options?: {
      readonly disableErrorReporting?: boolean | undefined
      readonly teardown?: Runtime.Teardown | undefined
    }
  ): <E, A>(effect: Effect<A, E>) => void
  /**
   * @since 1.0.0
   * @category Run main
   */
  <E, A>(
    effect: Effect<A, E>,
    options?: {
      readonly disableErrorReporting?: boolean | undefined
      readonly teardown?: Runtime.Teardown | undefined
    }
  ): void
} = Runtime.makeRunMain(({
  fiber,
  teardown
}) => {
  let receivedSignal = false

  fiber.addObserver((exit) => {
    process.removeListener("SIGINT", onSigint)
    process.removeListener("SIGTERM", onSigint)
    teardown(exit, (code) => {
      if (receivedSignal || code !== 0) {
        process.exit(code)
      }
    })
  })

  function onSigint() {
    receivedSignal = true
    fiber.interruptUnsafe(fiber.id)
  }

  process.on("SIGINT", onSigint)
  process.on("SIGTERM", onSigint)
})
