
throw new Error "unimplemented"

# TODO: Set internal/Type.compare with better comparison func

# noop = require "./internal/noop"

# _Type = require "./internal/Type"
# Factory = require "./internal/Factory"
# Constructor = require "./internal/Constructor"
# Validator = require "./internal/Validator"
# NamedFunction = require "./internal/NamedFunction"
# Kind = require "./internal/Kind"
# Property = require "./Property"
# Mixin = require "./Mixin"
# Null = require "./Null"
# Undefined = require "./Undefined"

# Type = Factory
# 	constructor: NamedFunction.Constructor
# 	options.validator ?= Validator { types: options.optionTypes, defaults: options.optionDefaults, validate: Type.validate }



Type = require "./internal/Type"

Type.init 

	validator: Validator
		types:
			name: String
			mixins: Array
			initializer: Function.Kind
			constructor: Function.Kind
			optionTypes: Object
			optionDefaults: Object
			external: Object
			internal: Object
			props:
				isType: Function
				isTypeOf: Function
			validator: Function
			constructor: Function
		defaults:
			kind: Object
			initializer: noop
			props: {}

	constructor: (initialize, opts) ->
		return NamedFunction.Constructor.call this, opts.name

	# initializer: (opts) ->
	# 	Object.defineProperty instance, name, { value, writable: true } for name, value of internal if internal?
	initializer: (opts) ->
		{ init, kind, external, props, mixins } = opts
		throw Error() unless isTypeOf opts.kind, Function
		Object.defineProperty this, "isConstructable", { value: opts.init? }
		mix this, mixins, =>
			addProps @prototype, opts.external if opts.external?
			_Type.checkers.set this, steal(opts.props, "isType")
			addProps this, opts.props
		setKind this, opts.kind
		opts.constructor ?= opts.kind.constructor
		factory = Factory opts
		return =>
			instance = factory.apply null, arguments
			return setConstructor instance, this

Type.of = _Type

TypeUtils._compareTypes = 


# Vyper Types
Type.register [
	Type
	Null
	Undefined
	Property
	Mixin
	Validator
]

# Type = _Type
	
# 	name: "Type"

# 	kind: Function

# 	spawner: _Type.Spawner

# 	validator: 
	
# 	init: (options) ->
# 		options.validator ?= Validator { types: options.optionTypes, defaults: options.optionDefaults, validate: Type.validate }
# 		_Type.init.call this, options
# 		return setConstructor this, Type

# 	props:

# 		of: _Type.of

# 		validate: (options) ->
# 			options.compare ?= _isEqualToTypeOf
# 			return Validator.validate options

# 	external:

# 		kind: Property
# 			get: -> 
# 				return Kind.get this

# 		kinds: Property
# 			get: -> 
# 				return Kind.list this

# 		isType: (type) ->
# 			return (_Type.checkers.get(this) ? _isEqualToType).call(this, type) and (type.isConstructable or (_Type.checkers.get(type) ? _alwaysTrue).call type, this)
		
# 		isTypeOf: (value) -> 
# 			return @isType _Type.of value

# 		isKind: (type) -> 
# 			return Kind.is { type, kind: this, compare: _areTypesEqual }

# 		isKindOf: (value) -> 
# 			return @isKind _Type.of value

# 		Kind: Property { get: -> _register Kind(this) }

# 		Constructor: Property { get: -> Constructor this }

# module.exports = Type

# ###

# Internal

# ###

# _areTypesEqual = (a, b) -> a.isType b

# _isEqualToTypeOf = (value, type) -> type.isTypeOf value

# _isEqualToType = (type) -> this is type

# _alwaysTrue = -> true


# noop = require "./noop"
# assert = require "./assert"
# addProps = require "./addProps"
# isTypeOf = require "./isTypeOf"
# Constructor = require "./Constructor"
# Kind = require "./Kind"
# steal = require "./steal"
# NamedFunction = require "./NamedFunction"
# Validator = require "./Validator"
# Spawner = require "./Spawner"

# { mix } = require "./../Mixin"

# _createType = (opts) ->
# 	opts.validator ?= Validator 
# 	type = NamedFunction.Spawner.call opts.name
# 	return _factory opts

# 	return _Type.init.call type, opts

# The factory for creating new Types.
_factory = Factory


# require "polymer-weakmap"
# _Type.checkers = new WeakMap()

# module.exports = _Type

