class Sus::Receive

def and_return(*returning)

def and_return(*returning)
	if returning.size == 1
		@returning = returning.first
	else
		@returning = returning
	end
	return self
end

def call(assertions, subject)

def call(assertions, subject)
	assertions.nested(self) do |assertions|
		mock = @base.mock(subject)
		
		called = 0
		
		if call_original?
			mock.before(@method) do |*arguments, **options, &block|
				called += 1
				
				validate(mock, assertions, arguments, options, block)
			end
		else
			mock.replace(@method) do |*arguments, **options, &block|
				called += 1
				
				validate(mock, assertions, arguments, options, block)
				
				next @returning
			end
		end
		
		if @times
			assertions.defer do
				@times.call(assertions, called)
			end
		end
	end
end

def call_original?

def call_original?
	@returning == CALL_ORIGINAL
end

def initialize(base, method)

def initialize(base, method)
	@base = base
	@method = method
	
	@times = Times.new
	@arguments = nil
	@options = nil
	@block = nil
	@returning = CALL_ORIGINAL
end

def once

def once
	@times = Times.new(Be.new(:==, 1))
	return self
end

def print(output)

def print(output)
	output.write("receive ", :variable, @method.to_s, :reset)
end

def twice

def twice
	@times = Times.new(Be.new(:==, 2))
	return self
end

def validate(mock, assertions, arguments, options, block)

def validate(mock, assertions, arguments, options, block)
	return unless @arguments or @options or @block
	
	assertions.nested(self) do |assertions|
		@arguments.call(assertions, arguments) if @arguments
		@options.call(assertions, options) if @options
		@block.call(assertions, block) if @block
	end
end

def with(*arguments, **options)

def with(*arguments, **options)
	with_arguments(Be.new(:==, arguments)) if arguments.any?
	with_options(Be.new(:==, options)) if options.any?
	return self
end

def with_arguments(predicate)

def with_arguments(predicate)
	@arguments = WithArguments.new(predicate)
	return self
end

def with_block(predicate = Be.new(:!=, nil))

def with_block(predicate = Be.new(:!=, nil))
	@block = WithBlock.new(predicate)
	return self
end

def with_call_count(predicate)

def with_call_count(predicate)
	@times = Times.new(predicate)
	return self
end

def with_options(predicate)

def with_options(predicate)
	@options = WithOptions.new(predicate)
	return self
end