{ TypeCheck } = require "check-args-impl"

class Signature extends TypeCheck
  @validate: -> new Signature().setArguments arguments...
  @with: @validate # alias
  @accept: ->
    new Signature().accept(arguments...)
  @after: @accept # alias
  accept: ->
    ret = super arguments...
    pattern = @patterns[@patterns.length-1]
    run: (fn)->
      pattern.callback = fn
      ret
  after: Signature::accept # alias
  createDummy: (pattern, args)->
    @check = -> [pattern, args]
    @patterns[@patterns.length] = pattern
    return empty =
        accept: -> run: -> empty
        after: -> run: -> empty
        get: =>
          @handle(pattern, @args)
        getWithContext: (context)=>
          @context = context
          @handle(pattern, @args)
  asMethod: ->
    typeCheck = this
    ->
      typeCheck.context = this
      typeCheck.handle typeCheck.check(arguments...)...
  asConstructor: ->
    typeCheck = this
    ->
      typeCheck.context = this
      typeCheck.handle typeCheck.check(arguments...)...
      undefined
  get: ->
    @checkFn = @get
    @handle @check(arguments...)...
  getWithContext: (context)->
    @context = context
    @checkFn = @getWithContext
    args = new Array arguments.length-1
    for arg, i in arguments when i > 0
      throw new Error "arguments object not allowed" if arg?.callee
      args[i-1] = arg
    @handle @check(args...)...
  handle: (pattern, args)->
    a = args[0...pattern.checksBefore.length]
    if pattern.checkRest?
      end = args.length - pattern.checksAfter.length
      a.push args[pattern.checksBefore.length ... end]
      a.push args[end...]...
    return pattern.callback.apply @context, a

module.exports = Signature
