 mock = (fn) ->
   mocks = ( new Mock() for i in [1..5] )
   fn.apply(undefined, mocks)
-  errors = ( mock._build_errors() for mock in mocks ).join("")
+  errors = ( _build_errors(mock) for mock in mocks ).join("")
   throw errors unless errors == ""
 
 

  #   console.log error   # prints "an error"
  #
  throws: (error) ->
    @_check_throws_usage(error)
    @_current_signature().throws = error
    @_set_state("throws")
    @
    
  #

  # my_mock.check()       # throws an error because your_method() was not called
  #
  check: ->
    _set_state(@, "check")
    _check_for_errors(@)
    @


    
# Private Mock 'methods'; making them functions keeps the Mock object uncluttered.

_set_state = (mock, state) ->
  mock.state = state
  
_is_state_in = (mock, states...) ->
  mock.state in states

_is_reserved_word = (word) ->
  word in [ "expects", "args", "returns", "check" ]

_check_expects_usage = (method_name) ->
  _throw_expects_usage() unless method_name?
  _throw_reserved_word(method_name) if _is_reserved_word(method_name)

_check_args_usage = (mock, args...) ->
  _throw_args_usage() if args.length == 0
  _throw_args_must_be_after_expects() unless _is_state_in(mock, "expects")

_check_returns_usage = (mock, value) ->
  _throw_returns_usage() unless value?
  _throw_returns_must_be_after_expects_or_args() unless _is_state_in(mock, "expects", "args")
    
_check_throws_usage = (mock, error) ->
  _throw_throws_usage(error) unless error?
  _throw_throws_must_be_after_expects_or_args() unless _is_state_in(mock, "expects", "args")
    
_check_if_duplicate_signature = (mock, method_name, args...) ->
  _throw_duplicate_expectation("#{method_name}(#{args})") if _find_signature(mock, method_name, args...)
      
_check_for_errors = (mock) ->
  errors = _build_errors(mock)
  throw errors unless errors == ""

_current_signature = (mock) ->
  mock.signatures[0]
  
_current_method_name = (mock) ->
  _current_signature(mock)?.method_name

_find_signature = (mock, method_name, args...) ->
  for signature in mock.signatures when signature.matches(method_name, args...)
    return signature
  undefined

_build_mocked_method = (mock, method_name) ->
  (args...) ->
    signature = _find_signature(mock, method_name, args...)
    _throw_unknown_expectation("#{method_name}(#{args})") unless signature?
    signature.called = true
    throw signature.throws if signature.throws?
    signature.returns

_build_errors = (mock) ->
  errors = ""
  for signature in mock.signatures when signature.called == false
    errors += "'#{signature.method_name}(#{signature.args})' was never called\n" 
  errors

_throw_expects_usage = ->
  throw "you need to supply a method name to .expects(), e.g. my_mock.expects('my_method')"

_throw_reserved_word = (reserved) ->
  throw "you cannot do my_mock.expects('#{reserved}'); '#{reserved}' is a reserved method name"
  
_throw_args_usage = ->
  throw "you need to supply at least one argument to .args(), e.g. my_mock.expects('my_method').args(42)"
  
_throw_args_must_be_after_expects = ->
  throw ".args() must be called immediately after .expects(), e.g. my_mock.expects('my_method').args(42)"
  
_throw_duplicate_expectation = (signature) ->
  throw "#{signature} is a duplicate expectation"
  
_throw_returns_usage = ->
  throw "you need to supply an argument to .returns(), e.g. my_mock.expects('my_method').returns(123)"
  
_throw_returns_must_be_after_expects_or_args = ->
  throw ".returns() must be called immediately after .expects() or .args()"
  
_throw_throws_usage = ->
  throw "you need to supply an argument to .throws(), e.g. my_mock.expects('my_method').throws('an error')"

_throw_throws_must_be_after_expects_or_args = ->
  throw ".throws() must be called immediately after .expects() or .args()"
    
_throw_unknown_expectation = (signature) ->
  throw "#{signature} does not match any expectations"

  

#
# mock() is a convenience function to ensure that _build_errors() is
