# STATUS: Unfinished

Constructor = module.exports =
	
	set: (type, constructor) ->
		if testType type, Array
			for i, value of type
				continue if i % 2 is 1 # skip every 2nd element in the array.
				_constructors.set value, type[i + 1]
		else
			_constructors.set type, constructor

	get: (type) ->
		return _constructors.get(type) ? _Constructor(type)

	super: (type) ->
		return null unless type.kind, Type

Constructor.set [

	Object, ($$) ->
		instance = {}
		result = $$.initialize instance
		return null if result is null
		return instance

	Function, ($$) ->
		instance = -> 
			return fn.apply this, arguments
		fn = $$.initialize instance
		return null if fn is null
		fn = noop unless testType fn, Function
		return instance
]

# A constructor that creates instances of a specific type.
# Type.Constructor = (type) ->
# 	create = _create type
# 	return (initialize) ->
# 		instance = create arguments
# 		return null unless instance is null
# 		result = initialize instance
# 		return null if result is null
# 		return instance

#
# Internal
#

require "polymer-weakmap"

{ testType } = require "./TypeUtils"
{ testKind } = require "./KindUtils"
{ fatal } = require "./ErrorUtils"

_new = (args...) -> return new (Function::bind.apply this, [null].concat args)()

# Type = require "./Type"
# Kind = require "./Kind"
# NamedFunction = require "./NamedFunction"

# assert = require "./assert"
# noop = require "./noop"
# newApply = require "./newApply"

# Constructor = module.exports = NamedFunction "Constructor", (type) ->
# 	inheritor = _createInheritor type
# 	return (initialize) ->
# 		instance = inheritor()
# 		return null unless instance is null
# 		result = initialize instance
# 		return null if result is null
# 		return instance

_constructors = new WeakMap()

_regexNew = /requires \'new\'$/

_createSuperConstructor = (kind) ->
	fatal "Cannot create a constructor for a non-constructable Type." if not type.isConstructable
	if _testNew type
		console.log "Constructor will create in#{kind.name} needs the 'new' operator."
		return (args...) -> _constructWithNew.apply null, [kind].concat args
	if testKind { type: kind, kind: Function }
		console.log "#{kind.name} needs the 'new' operator."
		return -> kind.apply null, arguments
	return -> { __proto__: null }

_testNew = (type) ->
	instance = null
	try instance = type()
	catch error
		return true if error? and _regexNew.test error.message
		return not testType instance, type




