 
 
 #
-# expects
-#
-expects = (method_name) ->
-  check_expects_usage(@, method_name)
-  create_expectation(@, method_name)
-
-check_expects_usage = (object, method_name) ->
-  throw_expects_usage() unless method_name?
-  throw_reserved_word(method_name) if is_reserved_word(method_name)
-  throw_pre_existing_property(method_name) if is_pre_existing_property(object, method_name)
-  throw_not_an_existing_method(method_name) if is_class(object) and not prototype_has_method(object, method_name)
-
-is_reserved_word = (word) ->
-  word in [ "expects", "args", "returns", "check" ]
-  
-is_pre_existing_property = (object, method_name) ->
-  object[ method_name ]? and (typeof object[ method_name ]) != 'function'
-  
-is_class = (object) ->
-   typeof object == 'function'
-   
-prototype_has_method = (object, method_name) ->
-   object.prototype[ method_name ]?
-
-create_expectation = (object, method_name) ->
-  new Expectation(object, method_name)
-
-throw_expects_usage = ->
-  throw new Error( "you need to supply a method name to expects(), e.g. my_mock.expects('my_method')" )
-
-throw_reserved_word = (reserved_word) ->
-  throw new Error( "you cannot use my_mock.expects('#{reserved_word}'); '#{reserved_word}' is a reserved method name" )
-  
-throw_pre_existing_property = (property_name) ->
-  throw new Error( "'#{property_name}' is an existing property; you can only mock functions" )
-  
-throw_not_an_existing_method = (method_name) ->
-  throw new Error( "'#{method_name}' is not an existing method; you can only mock existing methods on classes" )
+# Expects
+#
+class Expects
+  
+  @expects: (method_name) ->
+    _check_expects_usage(@, method_name)
+    _create_expectation(@, method_name)
+
+  # private
+
+  _check_expects_usage = (object, method_name) ->
+    _throw_expects_usage() unless method_name?
+    _throw_reserved_word(method_name) if _is_reserved_word(method_name)
+    _throw_pre_existing_property(method_name) if _is_pre_existing_property(object, method_name)
+    _throw_not_an_existing_method(method_name) if is_class(object) and not prototype_has_method(object, method_name)
+
+  _is_reserved_word = (word) ->
+    word in [ "expects", "args", "returns", "check" ]
+  
+  _is_pre_existing_property = (object, method_name) ->
+    object[ method_name ]? and (typeof object[ method_name ]) != 'function'
+  
+  _create_expectation = (object, method_name) ->
+    new Expectation(object, method_name)
+
+  _throw_expects_usage = ->
+    throw new Error( "you need to supply a method name to expects(), e.g. my_mock.expects('my_method')" )
+
+  _throw_reserved_word = (reserved_word) ->
+    throw new Error( "you cannot use my_mock.expects('#{reserved_word}'); '#{reserved_word}' is a reserved method name" )
+  
+  _throw_pre_existing_property = (property_name) ->
+    throw new Error( "'#{property_name}' is an existing property; you can only mock functions" )
+  
+  _throw_not_an_existing_method = (method_name) ->
+    throw new Error( "'#{method_name}' is not an existing method; you can only mock existing methods on classes" )
 
 
 #

# TODO: note about there not being that many expectations (i.e. typically fewer than 10?)
#
class AllExpectations
	
	@register_expectation: (expectation) ->
		_expectations.push(expectation)
		
	@find_expectation: (object, method_name, args...) ->
	  for expectation in _expectations when expectation.matches(object, method_name, args...)
	    return expectation
	  undefined

	@check_for_duplicate_expectations: ->
	  # TODO: use each with index and slice to avoid last element
	  return if _expectations.length < 2
	  for outer in [0.._expectations.length-2]
	    for inner in [outer+1.._expectations.length-1]
	      if _expectations[outer].equals( _expectations[inner] )
	        throw_duplicate_expectation("#{_expectations[outer]._method_name}(#{_expectations[outer]._args})")

	@verify_all_expectations: ->
		errors = _find_all_errors()
		throw new Error(errors) unless errors == ""

	# TODO: write comment about uninstalling in reverse
	# TODO: does this belong in unregister_all_expectsions?
	@uninstall_all_mocked_methods: ->
	  expectation.uninstall_mocked_method() for expectation in _expectations by -1
		
	# TODO: should this be called remove_all_expectations?  What about register_expectations?
	#       How about install_expectation() and uninstall_all_expectations()?
	@unregister_all_expectations: ->
		_expectations.length = 0
		
	# private
	
	_expectations = []
	
	_find_all_errors = ->
  	  ( expectation.find_errors() for expectation in _expectations ).join("")
  
  
#

    AllExpectations.unregister_all_expectations()

install_expects_method = ->
  Object.prototype.expects = Expects.expects

uninstall_expects_method = ->
  delete Object.prototype.expects
