class RSpec::Mocks::AnyInstance::Recorder

def already_observing?(method_name)

def already_observing?(method_name)
  @observed_methods.include?(method_name)
end

def backup_method!(method_name)

def backup_method!(method_name)
  alias_method_name = build_alias_method_name(method_name)
  @klass.class_eval do
    if method_defined?(method_name)
      alias_method alias_method_name, method_name
    end
  end
end

def build_alias_method_name(method_name)

def build_alias_method_name(method_name)
  "__#{method_name}_without_any_instance__"
end

def each_expectation_filfilled?

def each_expectation_filfilled?
  @message_chains.all? do |method_name, chain|
    chain.expectation_filfilled?
  end
end

def has_expectation?(method_name)

def has_expectation?(method_name)
  @message_chains[method_name].is_a?(ExpectationChain)
end

def initialize(klass)

def initialize(klass)
  @message_chains = {}
  @observed_methods = []
  @played_methods = {}
  @klass = klass
  @expectation_set = false
end

def instance_that_received(method_name)

def instance_that_received(method_name)
  @played_methods[method_name]
end

def mark_invoked!(method_name)

def mark_invoked!(method_name)
  backup_method!(method_name)
  @klass.class_eval(<<-EOM, __FILE__, __LINE__)
    def #{method_name}(*args, &blk)
      method_name = :#{method_name}
      current_instance = self
      invoked_instance = self.class.__recorder.instance_that_received(method_name)
      raise RSpec::Mocks::MockExpectationError, "The message '#{method_name}' was received by \#{self.inspect} but has already been received by \#{invoked_instance}"
    end
  EOM
end

def observe!(method_name)

def observe!(method_name)
  stop_observing!(method_name) if already_observing?(method_name)
  @observed_methods << method_name
  backup_method!(method_name)
  @klass.class_eval(<<-EOM, __FILE__, __LINE__)
    def #{method_name}(*args, &blk)
      self.class.__recorder.playback!(self, :#{method_name})
      self.send(:#{method_name}, *args, &blk)
    end
  EOM
end

def playback!(instance, method_name)

def playback!(instance, method_name)
  RSpec::Mocks::space.add(instance)
  @message_chains[method_name].playback!(instance)
  @played_methods[method_name] = instance
  received_expected_message!(method_name) if has_expectation?(method_name)
end

def received_expected_message!(method_name)

def received_expected_message!(method_name)
  @message_chains[method_name].expectation_fulfilled!
  restore_method!(method_name)
  mark_invoked!(method_name)
end

def remove_dummy_method!(method_name)

def remove_dummy_method!(method_name)
  @klass.class_eval do
    remove_method method_name
  end
end

def restore_method!(method_name)

def restore_method!(method_name)
  if @klass.method_defined?(build_alias_method_name(method_name))
    restore_original_method!(method_name)
  else
    remove_dummy_method!(method_name)
  end
end

def restore_original_method!(method_name)

def restore_original_method!(method_name)
  alias_method_name = build_alias_method_name(method_name)
  @klass.class_eval do
    alias_method  method_name, alias_method_name
    remove_method alias_method_name
  end
end

def should_receive(method_name, *args, &block)

def should_receive(method_name, *args, &block)
  observe!(method_name)
  @expectation_set = true
  @message_chains[method_name] = ExpectationChain.new(method_name, *args, &block)
end

def stop_all_observation!

def stop_all_observation!
  @observed_methods.each do |method_name|
    restore_method!(method_name)
  end
end

def stop_observing!(method_name)

def stop_observing!(method_name)
  restore_method!(method_name)
  @observed_methods.delete(method_name)
end

def stub(method_name, *args, &block)

def stub(method_name, *args, &block)
  observe!(method_name)
  @message_chains[method_name] = StubChain.new(method_name, *args, &block)
end

def unfulfilled_expectations

def unfulfilled_expectations
  @message_chains.map do |method_name, chain|
    method_name.to_s if chain.is_a?(ExpectationChain) unless chain.expectation_filfilled?
  end.compact
end

def verify

def verify
  if @expectation_set && !each_expectation_filfilled?
    raise RSpec::Mocks::MockExpectationError, "Exactly one instance should have received the following message(s) but didn't: #{unfulfilled_expectations.sort.join(', ')}"
  end
end