BindingInterface:: = Object.create BindingInterfacePrivate,
	of:					get: ()-> METHOD_of if not @stage			#=== if stage is 0
	set:				get: ()-> METHOD_set if @stage				#=== if stage is 1 or 2
	chainTo:			get: ()-> METHOD_chainTo if @stage is 2
	transformSelf:		get: ()-> METHOD_transformSelf if @stage is 1
	transform:			get: ()-> METHOD_transform if @stage is 2
	transformAll:		get: ()-> METHOD_transformAll if @stage is 2
	condition:			get: ()-> METHOD_condition if @stage is 2
	conditionAll:		get: ()-> METHOD_conditionAll if @stage is 2
	bothWays:			get: ()-> METHOD_bothWays if @stage is 2
	unBind:				get: ()-> METHOD_unBind if @stage is 2
	pollEvery:			get: ()-> METHOD_pollEvery if @stage #=== if stage is 1 or 2
	stopPolling:		get: ()-> METHOD_stopPolling if @stage #=== if stage is 1 or 2
	setOption:			get: ()-> METHOD_setOption if @stage is 2
	disallowFrom:		get: ()-> if @stage is 2 and (thisInterface=@)
							genProxiedInterface false, (disallowInterface)->
								subInterface = thisInterface.subs[thisInterface.subs.length-1]
								thisInterface._.addDisallowRule(subInterface._, disallowInterface._)

								return thisInterface
	
	updateOn:			get: ()-> if @stage and (thisInterface=@) #=== if stage is 1 or 2
							genProxiedInterface false, (subInterface)->
								if subInterface._ isnt thisInterface._
									thisInterface._.pubsMap[subInterface._.ID] = subInterface._
									subInterface._.addSub genSelfUpdater(thisInterface._, true), subInterface.options, false, true
								
								return thisInterface
	

	removeUpdater:		get: ()-> if @stage and (thisInterface=@) and (selfUpdater=@_.selfUpdater) #=== if stage is 1 or 2
							genProxiedInterface false, (subInterface)->
								if subInterface._.subsMeta[selfUpdater.ID]
									delete thisInterface._.pubsMap[subInterface._.ID]
									subInterface._.removeSub(selfUpdater)

								return


	to:					get: ()-> if @stage is 1 and (thisInterface=@)
							genProxiedInterface true, (subInterface)->
								if subInterface._ isnt thisInterface._
									subInterface.addToPublisher(thisInterface)
								
								return thisInterface
	

	and:				get: ()->
							cloneInterface = @selfClone()
							if @stage is 2
								return cloneInterface
						
							else if @stage is 1
								if not cloneInterface._.isMulti
									cloneBinding = cloneInterface._
									cloneInterface._ = cloneInterface._ = new GroupBinding(cloneInterface)
									cloneInterface._.addBinding(cloneBinding)
								
								return genProxiedInterface false, (siblingInterface)->
									cloneInterface._.addBinding(siblingInterface._)
									return cloneInterface
	

	once:				get: ()-> if @stage is 1
							interfaceToReturn = @selfClone()
							interfaceToReturn.updateOnce = true
							return interfaceToReturn

	# ==== Aliases =================================================================================
	update:				get: ()-> @set
	twoWay:				get: ()-> @bothWays
	pipe:				get: ()-> @chainTo




METHOD_of = (object)->
	throwErrorBadArg(object) unless checkIf.isObject(object) or checkIf.isFunction(object)
	
	if checkIf.isBindingInterface(object)
		object = object.object

	@stage = 1
	return @setObject(object)





METHOD_chainTo = (subject, specificOptions, saveOptions)->
	return SimplyBind(@subs[@subs.length-1]).to(subject, specificOptions, saveOptions)





METHOD_set = (newValue)->
	@_.setValue(newValue)
	return @








METHOD_transformSelf = (transformFn)-> # Applied only to the last sub
	if not checkIf.isFunction(transformFn)
		throwWarning('fnOnly',1)
	else
		@_.setSelfTransform(transformFn, @options.updateOnBind)
		
	return @


METHOD_transform = (transformFn)-> # Applied only to the last sub
	@_.addModifierFn('transformFn', @subs.slice(-1), transformFn, @options.updateOnBind)
	return @


METHOD_transformAll = (transformFn)-> # Applied to entrie subs set		
	@_.addModifierFn('transformFn', @subs, transformFn, @options.updateOnBind)
	return @






METHOD_condition = (conditionFn)-> # Applied only to the last sub
	@_.addModifierFn('conditionFn', @subs.slice(-1), conditionFn)
	return @


METHOD_conditionAll = (conditionFn)-> # Applied to entrie subs set
	@_.addModifierFn('conditionFn', @subs, conditionFn)
	return @







METHOD_bothWays = (altTransform)-> # Applied only to the last sub
	sub = @subs[@subs.length-1] # Last Proxied
	subBinding = sub._
	bindings = if @_.isMulti then @_.bindings else [@_]

	subBinding.addSub(@_, sub.options)
	
	for binding in bindings
		originTransform = binding.subsMeta[subBinding.ID].transformFn
		originCondition = binding.subsMeta[subBinding.ID].conditionFn

		if originTransform or altTransform
			transformToUse = if checkIf.isFunction(altTransform) then altTransform else originTransform
			subBinding.subsMeta[@_.ID].transformFn = transformToUse if transformToUse and altTransform isnt false

		if originCondition
			subBinding.subsMeta[@_.ID].conditionFn = originCondition

	return @



METHOD_unBind = (bothWays)-> # Applied to all subs
	@_.removeSub(sub._, bothWays) for sub in @subs
	return @





METHOD_pollEvery = (time)->
	@_.addPollInterval(time)
	return @



METHOD_stopPolling = ()->
	@_.removePollInterval()
	return @



METHOD_setOption = (optionName, newValue)->
	@_.subsMeta[@subs[@subs.length-1]._.ID].opts[optionName] = newValue	
	return @
























