class BCDD::Result::Context < BCDD::Result
  EXPECTED_OUTCOME: String

  SourceMethodArity: ^(Method) -> Integer

  attr_reader acc: Hash[Symbol, untyped]

  def initialize: (
    type: Symbol,
    value: untyped,
    ?source: untyped,
    ?expectations: BCDD::Result::Contract::Evaluator,
    ?terminal: bool
  ) -> void

  def and_then: (?Symbol, **untyped) ?{ (Hash[Symbol, untyped]) -> untyped } -> untyped

  def and_then!: (untyped, **untyped) -> untyped

  private

  def call_and_then_source_method: (Symbol, Hash[Symbol, untyped]) -> BCDD::Result::Context

  def call_and_then_callable!: (untyped, value: untyped, injected_value: untyped, method_name: (Symbol | nil)) -> BCDD::Result::Context

  def ensure_result_object: (untyped, origin: Symbol) -> BCDD::Result::Context

  def raise_unexpected_outcome_error: (BCDD::Result::Context | untyped, Symbol) -> void
end

class BCDD::Result::Context
  class Success < BCDD::Result::Context
    include BCDD::Result::Success::Methods

    def and_expose: (Symbol, Array[Symbol], terminal: bool) -> BCDD::Result::Context::Success
  end

  def self.Success: (Symbol, **untyped) -> BCDD::Result::Context::Success
end

module BCDD::Result::Context::CallableAndThen
  class Caller < BCDD::Result::CallableAndThen::Caller
    module KeyArgs
      def self.parameters?: (untyped) -> bool

      def self.invalid_arity: (untyped, Symbol) -> BCDD::Result::CallableAndThen::Error::InvalidArity
    end

    def self.call: (
      untyped source,
      value: untyped,
      injected_value: untyped,
      method_name: (Symbol | nil),
    ) -> BCDD::Result::Context

    private

    def self.call_proc!: (
      untyped source,
      Hash[Symbol, untyped] value,
      nil injected_value
    ) -> BCDD::Result::Context

    def self.call_method!: (
      untyped source,
      Method method,
      Hash[Symbol, untyped] value,
      nil injected_value
    ) -> BCDD::Result::Context

    def self.callable_method: (
      untyped source,
      (Symbol | nil) method_name
    ) -> ::Method

    def self.ensure_result_object: (
      untyped source,
      untyped value,
      BCDD::Result::Context result
    ) -> BCDD::Result::Context

    def self.expected_result_object: () -> singleton(BCDD::Result::Context)

    def self.expected_outcome: () -> String
  end
end

class BCDD::Result::Context
  class Failure < BCDD::Result::Context
    include BCDD::Result::Failure::Methods

    def and_expose: (Symbol, Array[Symbol], **untyped) -> BCDD::Result::Context::Failure
  end

  def self.Failure: (Symbol, **untyped) -> BCDD::Result::Context::Failure
end

class BCDD::Result::Context
  module Mixin
    Factory: singleton(BCDD::Result::Mixin::Factory)

    module Methods
      def Success: (Symbol, **untyped) -> BCDD::Result::Context::Success

      def Failure: (Symbol, **untyped) -> BCDD::Result::Context::Failure

      private

      def _ResultAs: (singleton(BCDD::Result::Context), Symbol, untyped, ?terminal: bool) -> untyped
    end

    module Addons
      module Continue
        include BCDD::Result::Context::Mixin::Methods

        private

        def Continue: (**untyped) -> BCDD::Result::Context::Success
      end

      module Given
        include BCDD::Result::Context::Mixin::Methods

        private

        def Given: (*untyped) -> BCDD::Result::Context::Success
      end

      OPTIONS: Hash[Symbol, Module]

      def self.options: (Hash[Symbol, Hash[Symbol, bool]]) -> Hash[Symbol, Module]
    end
  end

  def self.mixin_module: -> singleton(BCDD::Result::Context::Mixin)

  def self.result_factory: -> singleton(BCDD::Result::Context)
end

class BCDD::Result::Context::Expectations < BCDD::Result::Expectations
  def self.mixin_module: -> singleton(BCDD::Result::Context::Expectations::Mixin)

  def self.result_factory_without_expectations: -> singleton(BCDD::Result)

  def Success: (Symbol, **untyped) -> BCDD::Result::Context::Success
  def Failure: (Symbol, **untyped) -> BCDD::Result::Context::Failure
end

module BCDD::Result::Context::Expectations::Mixin
  Methods: singleton(BCDD::Result::Expectations::Mixin::Methods)
  Factory: singleton(BCDD::Result::Expectations::Mixin::Factory)

  module Addons
    module Continue
      private def Continue: (**untyped) -> BCDD::Result::Context::Success
    end

    module Given
      private def Given: (*untyped) -> BCDD::Result::Context::Success
    end

    OPTIONS: Hash[Symbol, Module]

    def self.options: (Hash[Symbol, Hash[Symbol, bool]]) -> Hash[Symbol, Module]
  end
end