# STATUS: Untested

NamedFunction = require "./internal/NamedFunction"

Property = module.exports = NamedFunction "Property", (property) ->
	property = { lazy: property } if testType property, Function
	validateTypes opts, _specs.Property
	return setType property, Property

Property::define = (object, key) ->
	Object.defineProperty object, key, PropertyDescriptor this


#
# Internal
#

{ noop } = require "./internal/FunctionUtils"
{ validateTypes, getType, setType, testType } = require "./internal/TypeUtils"
{ validateKind, getKind } = require "./internal/Kind"

_specs =

	Property:
		value: noop
		lazy: validateKind Function
		type: validateKind Type
		willSet: [Function, noop]
		didSet: [Function, noop]
		get: [Function, -> arguments[0]]
		set: [Function, -> arguments[0]]
		enumerable: [Boolean, false]
		writable: [Boolean, false]
		configurable: [Boolean, false]

PropertyDescriptor = (opts) ->
	{ value, enumerable, writable, configurable } = opts

	get = null

	if opts.lazy?
		get = ->
			return opts.get.call this, if value isnt undefined then value else (value = opts.lazy.call this)

	else
		get = ->
			return opts.get.call this, value

	set = (newValue) ->
		opts.willSet.call this, newValue, value
		oldValue = value
		value = opts.set.call this, newValue, oldValue
		opts.didSet.call this, oldValue, value
		return value

	return { get, set, enumerable, writable, configurable }



# Property.call = (obj, key, receiver, args...) ->
# 	fn = @of obj, key
# 	return new Error "property does not exist" unless fn?
# 	return fn.apply receiver, args if isTypeOf fn, Function
# 	return new Error "property is not a function"

# # `obj` must be an instance
# Property.of = (obj, key) ->
