import [browserOnly] closure-helpers-changeEvent.coffee
arrayMutatorMethods = ['push','pop','shift','unshift','splice','reverse','sort']
dummyPropertyDescriptor = {}

genID = ()-> 'sb_'+(Math.floor((1+Math.random()) * 1000000000000).toString(16))
genObj = ()-> Object.create(null)


# ==== Checks =================================================================================
arrayIncludes = (arr, item)-> arr.indexOf(item) isnt -1

checkIf =
	isDefined: (subject)-> subject isnt undefined
	
	isObject: (subject)-> typeof subject is 'object' and subject # 2nd check is to test against 'null' values

	isString: (subject)-> typeof subject is 'string'
	
	isNumber: (subject)-> typeof subject is 'number'
	
	isFunction: (subject)-> typeof subject is 'function'

	isBindingInterface: (subject)-> subject instanceof BindingInterface
	
	import [browserOnly] closure-helpers-checkIf.DOM.coffee





# ==== Options =================================================================================
setOptionsForBinding = (binding, newOptions)->
	for option,value of newOptions
		binding.options[option] = value if checkIf.isDefined(globalOptions[option])
	
	binding.makePropertyLive()
	return


extendState = (base, stateToInherit)->
	stateMapping = Object.keys(stateToInherit)
	base[key] = stateToInherit[key] for key in stateMapping
	return







# ==== Binding Cache =================================================================================
cache =	
	get: (object, isSimpleObject, selector, isMultiChoice)->
		if isSimpleObject
			return boundInstances[object._sb_ID]

		else
			import [browserOnly] closure-helpers-cache.get.DOMChoice_group.coffee
			if object._sb_map and object._sb_map[selector]
				return boundInstances[ object._sb_map[selector] ]


	set: (B, isSimpleObject)-> # B ==== Binding Object
		if isSimpleObject
			Object.defineProperty B.object, '_sb_ID', {'configurable':true, 'value':B.ID}

		else
			selector = B.selector

			if B.object._sb_map
				B.object._sb_map[selector] = B.ID
			else
				propsMap = {}
				propsMap[selector] = B.ID
				
				Object.defineProperty B.object, '_sb_map', {'configurable':true, 'value':propsMap}
		return

















# ==== Placeholders =================================================================================
escapeRegEx = /[.*+?^${}()|[\]\\]/g
pholderRegEx = pholderRegExSplit = null

setPholderRegEx = ()->
	start = globalOptions.placeholder[0].replace(escapeRegEx, '\\$&')
	end = globalOptions.placeholder[1].replace(escapeRegEx, '\\$&')
	middle = "[^#{end}]+"
	pholderRegEx = new RegExp("#{start}(#{middle})#{end}", 'g')
	pholderRegExSplit = new RegExp("#{start}#{middle}#{end}", 'g')
	return




applyPlaceholders = (contexts, values, indexMap)->
	output = ''
	for contextPart,index in contexts
		output += contextPart
		output += values[indexMap[index]] if indexMap[index]
	
	return output

import [browserOnly] closure-helpers-scanTextNodesPlaceholders.coffee








# ==== Errors + Warnings =================================================================================
throwError = (errorName)->
	throw new Error 'SimplyBind: '+(errors[errorName] or errorName)

throwWarning = (warningName, depth)-> unless globalOptions.silent
	errSource = getErrSource(depth)
	warn = errors[warningName]
	warn += "\n\n"+errSource
	console.warn('SimplyBind: '+warn)
	return

throwErrorUnavail = (methodName)->
	throwError "You can't use/invoke .#{methodName}() at this stage", true
	return

throwErrorBadArg = (methodName, arg)->
	throwError "Invalid argument/s (#{arg}) passed to .#{methodName}()", true
	return

getErrSource = (depth)->
	((new Error).stack or '')
		.split('\n')
		.slice(depth+3)
		.join('\n')






