 #----------------------------------------------
 
 #### 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:


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

#regexps
trailingSlash = /\/$/

# ちょっと大げさな気もするけど外部的には変わらんし
# 今後を見据えてクラス化しておく
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)


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