class Shoulda::Matchers::Doublespeak::Double

@private

def activate

def activate
  unless @activated
    store_original_method
    replace_method_with_double
    @activated = true
  end
end

def activated?

def activated?
  @activated
end

def call_original_method(call)

def call_original_method(call)
  unbound_method = world.original_method_for(klass, call.method_name)
  if unbound_method
    unbound_method.bind(call.object).call(*call.args, &call.block)
  end
end

def deactivate

def deactivate
  if @activated
    restore_original_method
    @activated = false
  end
end

def initialize(world, klass, method_name, implementation)

def initialize(world, klass, method_name, implementation)
  @world = world
  @klass = klass
  @method_name = method_name
  @implementation = implementation
  @activated = false
  @calls = []
  if world.doubles_activated?
    activate
  end
end

def record_call(call)

def record_call(call)
  calls << call
end

def replace_method_with_double

def replace_method_with_double
  double = self
  implementation = @implementation
  _method_name = method_name
  if klass.instance_methods(false).include?(method_name)
    klass.__send__(:remove_method, method_name)
  end
  klass.__send__(:define_method, method_name) do |*args, &block|
    call = MethodCall.new(
      double: double,
      object: self,
      method_name: _method_name,
      args: args,
      block: block,
      caller: caller
    )
    implementation.call(call)
  end
end

def restore_original_method

def restore_original_method
  original_method = world.original_method_for(klass, method_name)
  klass.__send__(:remove_method, method_name)
  klass.__send__(:define_method, method_name) do |*args, &block|
    original_method.bind(self).call(*args, &block)
  end
end

def store_original_method

def store_original_method
  world.store_original_method_for(klass, method_name)
end

def to_return(value = nil, &block)

def to_return(value = nil, &block)
  if block
    implementation.returns(&block)
  else
    implementation.returns(value)
  end
end