 #----------------------------------------------
 
 #### Copyrights
-#	(c) 2013 Eikichi Yamaguchi
-#	kazitori.js may be freely distributed under the MIT license.
-#	http://dev.hageee.net
-
-#	inspired from::
+# (c) 2013 Eikichi Yamaguchi
+# kazitori.js may be freely distributed under the MIT license.
+# http://dev.hageee.net
+
+# inspired from::
 #     (c) 2010-2012 Jeremy Ashkenas, DocumentCloud Inc.
 #     Backbone may be freely distributed under the MIT license.
 #     For all details and documentation:

# ちょっと大げさな気もするけど外部的には変わらんし
# 今後を見据えてクラス化しておく
class Rule
	rule:null
	_regexp:null
	callback:null
	router:null
	isVariable:false
	types:[]
	constructor:(string, callback, router)->
		@rule = string
		@callback = callback
		@_regexp = @_ruleToRegExp(string)
		#これ…どうなんだろ…
		@router = router
		@types = []

		re = new RegExp(namedParam)
		matched = string.match(re)
		if matched isnt null
			@isVariable = true
			for m in matched
				t = m.match(genericParam)||null
				@types.push if t isnt null then t[1] else null

	#マッチするかどうかテスト
	# **args**
	# fragment : テスト対象となる URL
	# **return**
	# Boolean : テスト結果の真偽値
	test:(fragment)->
		return @_regexp.test(fragment)

	#URL パラメータを分解
	_extractParams:(fragment)->
		param = @_regexp.exec(fragment)
		if param?
			newParam = param.slice(1)
			last = param[param.length - 1]
			if last.indexOf('?') > -1
				newQueries = []
				queries = last.split('?')[1]
				queryParams = queries.split('&')
				for query in queryParams
					kv = query.split('=')
					k = kv[0]
					v = if kv[1] then kv[1] else ""
					if v.indexOf('|') > -1
						v = v.split("|")
					obj = {}
					obj[k] = v
					newQueries.push obj
				newParam.pop()
				newParam.push last.split('?')[0]
				newParam.push {"queries":newQueries}
			return newParam
		else
			return null

	#パラメーターを指定された型でキャスト
	_getCastedParams:(params)->
		i = 0
		len = params.length
		castedParams = []
		while i < len
			if @types[i] is null
				castedParams.push params[i]
			else if typeof params[i] is "object"
				castedParams.push params[i]
			else
				for type in VARIABLE_TYPES
					if @types[i] is type.name
						castedParams.push type.cast(params[i])
			i++
		return castedParams

	_ruleToRegExp:(rule)->
		newRule = rule.replace(escapeRegExp, '\\$&')
		newRule = newRule.replace(optionalParam, '(?:$1)?')
		newRule = newRule.replace(namedParam, '([^\/]+)')
		newRule = newRule.replace(splatParam, '(.*?)')
		return new RegExp('^' + newRule + '$')




class EventDispatcher
	listeners:{}
	addEventListener:(type, listener)->
		if @listeners[ type ] is undefined
			@listeners[ type ] =[]

		if @listeners[type].indexOf listener is -1
			@listeners[type].push listener
		return

	removeEventListener:(type, listener)->
		len = 0
		for prop of @listeners
			len++
		if len < 1
			return
		arr = @listeners[type]
		if not arr
			return
		i = 0
		len = arr.length
		while i < len
			if arr[i] is listener
				if len is 1
					delete @listeners[type]
				else arr.splice(i,1)
				break
			i++
		return

	dispatchEvent:(event)->
		ary = @listeners[ event.type ]
		if ary isnt undefined
			event.target = @

			for handler in ary
				handler.call(@, event)
		return

## Deffered
# **internal**
# before を確実に処理するための簡易的な Deffered クラス
class Deffered extends EventDispatcher
	queue : []

	constructor:()->
		@queue = []
	
	deffered:(func)->
		@queue.push func
		return @

	execute:()->
		try
			task = @queue.shift()
			if task
				task.apply(@, arguments)
			if @queue.length < 1
				@queue = []
				@.dispatchEvent(new KazitoriEvent(KazitoriEvent.TASK_QUEUE_COMPLETE))
		catch error			
			@reject(error)

	reject:(error)->
		message = if not error then "user reject" else error
		@dispatchEvent({type:KazitoriEvent.TASK_QUEUE_FAILED, index:@index, message:message })



## KazitoriEvent
# Kazitori がディスパッチするイベント
class KazitoriEvent
	next:null
	prev:null
	type:null

	constructor:(type, next, prev)->
		@type = type
		@next = next
		@prev = prev

	clone:()->
		return new KazitoriEvent(@type, @next, @prev)

	toString:()->
		return "KazitoriEvent :: " + "type:" + @type + " next:" + String(@next) + " prev:" + String(@prev)


#タスクキューが空になった


#delegate
delegater = (target, func)->
  return ()->
    func.apply(target, arguments)

#regexps
trailingSlash = /\/$/
