$.ajaxSetup
  beforeSend:(xhr)->
    xhr.setRequestHeader 'Accept', 'application/json'
  cache: false

ViewHelpers=
  el_template:(path)->
    attrs = if typeof @model.attrs() is 'function'
      @model.attrs()
    else
      @model.attributes
    html  = @template path, attrs
    $(@el).html html
  fire:(event)->
    $(@el).trigger event
  bind_render:->
    _.bindAll        @      , 'render'
    @collection.bind 'add'  , @render
    @collection.bind 'reset', @render
  validate:->
    Backbone.Validation.bind @,
      invalid: (view, attr, error, selector)->
        l = $("label[for=document_#{attr}]").html()
        $('.errors').addClass 'on'
        $('.errors').append "<tr class='error'><td class='name'>#{l}</td><td>#{error}</td></tr>"
ModelHelpers=
  attrs:->
    attrs       = {}
    self        = @
    attrs       = @toJSON()
    attrs['id'] = @id if @id
    _.each attrs, (value,attr)->
      a = @get.call this, attr
      a = this[attr](a) if typeof this[attr] == 'function'
      attrs[attr] = a
    ,this
    attrs
CollectionHelpers =
  # @collection.collect
  # ---------------
  #
  # This method is best used with the BackboneHelpers.collect
  # In your view that has a collection you can call collect on
  # the collection and it will render the the individual models
  # if you used BackboneHelpers.collect to render the current
  # view all you have to do now is:
  #
  #    (assuming @collect 'projects' was called)
  #    @collection.collect
  #
  #  This would render the template 'projects/index' and attach
  #  it the '.projects'
  #
  #  if you don't want to render a template because it already exists
  #  you can just set has_template_index to false
  collect:->
    e         = $ @context.el
    find      = arguments[0]
    has_find  = find isnt undefined
    options   = arguments[1]
    options ||= {}
    ti   = options.template_index
    delete options.template_index
    template_index = "#{@name}/index"
    html  = @context.template template_index, {}
    html  = @context.template v, {} if ti isnt undefined

    hti  = options.has_template_index
    delete options.has_template_index
    e.html html if hti != false

    t    = options.template
    delete options.template
    template = "#{@name}/#{@name.singularize()}"
    template = t if t isnt undefined
    selector = e
    selector = e.find(find) if has_find
    primer   =  options.primer || template_index
    selector.html ''
    if @length == 0
      html = @context.template "#{primer}_primer", {}
      e.html html
    else
      for model in @context.collection.models
        options['model'] = model
        e = @context.partial null, template, options
        selector.append e.el
BackboneHelpers =
  redirect_on_browse:->
    if @browsing()
      return window.location.pathname = '/signup'
    else
      false
  browsing:->
    $('body').hasClass('browse_pages')
  hash:(i=null)->
    e = window.location.hash.replace /#/, ''
    e = e.replace /\?.+$/, ''
    e = e.split '/'
    if i then e[i] else e
  template: (path,data)->
    template = null
    eval "template = Template.#{path.replace(/\//g,'.')}"
    new throw "template is undefined: Template.#{path.replace(/\//g,'.')}" if template is undefined
    Milk.render template, data

  # collect
  # ---------------
  # This method makes it easy to quickly render a collection.
  # all you need to do is pass in the name of the collection you
  # want to be rendered eg.
  #
  #    collect 'projects'
  #
  # If your dealing with an association:
  #
  #   collect 'projects/tasks', id: 5
  #
  # It will create a collection in this case App.Collections.Projects
  # with the model being App.Models.Project and an url with '/projects'.
  # The collection will be assigned to the @collection instance variable
  # so you can reference it in your view. It will not invoke fetch().
  #
  # It will also called @partial '.projects', 'projects/index' and
  # attach the collection and whatever options you pass to to the
  # collect method.
  #
  # If you want to override the el of the partial you just need to specify
  # the el the option. eg.
  #
  #    @collect 'users', el: '.people'
  #
  # If you want to override the partial path thats being used in the partial you just
  # need to specify the template option (probably should not be called template since
  # that might confuse people with the actual template being render) eg.
  #
  #    #collect 'users', template: 'awesome_people/index'
  #
  # If you want to override the model being use you need to pass just the
  # model name to the model option eg.
  #
  #    @collect 'groups', model: 'community'
  #
  collect:->
    name      = arguments[0]
    options   = arguments[1]
    options ||= {}
    url = if name.match(/\//)
      e        = name.split '/'
      context  = e[0]
      name     = e[1]
      reg      = new RegExp "#{context}\\/(\\d+)"
      id       = options.id
      "/#{context}/#{id}/#{name}"
    else
      "/#{name}"
    klass      = name.camelize()
    has_model  = options['model'] isnt undefined
    model_name = if has_model
      model_name = options['model']
      delete options['model']
      model_name.camelize()
    else if @model_name
      model_name = @model_name
      model_name.camelize()
    else
      klass.singularize()
    @collection               = new App.Collections[klass]
    result_model = @result_model || "#{model_name}Result"
    if App.Models[result_model]
      @collection.results_model = new App.Models[result_model]()
      @collection.results_model.collection = @collection
    @collection.model         = App.Models[model_name]
    @collection.url           = url
    @collection.name          = name
    options                 ||= {}
    options.collection        = @collection

    selector = ".#{name}"
    if options['el'] isnt undefined
      selector = options['el']
      delete options['el']

    template = "#{name}/index"
    if options['template'] isnt undefined
      template = options['template']
      delete options['template']
    e = @partial selector, template, options
    @collection.context = e
    @collection
  partial:->
    el      = arguments[0]
    name    = arguments[1]
    options = arguments[2]
    scope = 'App'
    if name.match /admin/
      scope = 'Admin'
      name = name.replace /admin\//, ''
    e              = name.split '/'
    options      ||= {}
    options['el']  = el if el != null
    p = (item.camelize() for item in e)
    eval "var p = new #{scope}.Views.#{p.join('.')}(options)"
    instance_var = e.join('_')
    @[instance_var] = p
  post:(url,success,data)->
    token = $("meta[name='csrf-token']").attr('content')
    data['authenticity_token'] = token
    $.ajax
      type     : 'post'
      url      : url,
      data     : data
      dataType : 'json'
      context  : this
      success  : success
  get:(url,success,data)->
    $.ajax
      url      : url,
      data     : data
      dataType : 'json'
      context  : this
      success  : success
  resize:->
    App.Helpers.Base.resize_panels()
_.extend Backbone.Router.prototype    , BackboneHelpers
_.extend Backbone.View.prototype      , BackboneHelpers
_.extend Backbone.View.prototype      , ViewHelpers
_.extend Backbone.Model.prototype     , ModelHelpers
_.extend Backbone.Collection.prototype, CollectionHelpers

class App.Routers.Queryable extends Backbone.Router
  get_name:->
    @alias || @name
  initialize:->
    @collect @name, el: '.content'
    @routes             ||= {}
    n                    = @name
    n                    = @alias if @alias
    group_path           = "groups/:group_id/#{n}"
    @routes[group_path]  = 'group_index' if @group
    @routes[n]           = 'index'
    @routes["#{n}?:q"] = 'query'
    if @with_heading
      _.bindAll @, 'heading'
      $('.heading').on 'group', @heading
    @_bindRoutes()
  index:->
    Search.data = {}
    $('#search').val null
    if @with_heading
      $('.column').trigger 'expand'
    if App.skip
      App.skip = false
    else
      @collection.fetch_results()
  query:(data)->
    data        = $.deserialize_hash data
    Search.data = data
    $('.column').trigger 'expand'
    $('#search').trigger 'register', @
    $('#search').val data.q
    $('#search').trigger 'engage', data
  group_index:(id)->
    @collection.fetch_results
      group: id
      url: "/#{@name}"
  heading:->
    $('.wrapper').addClass 'with_heading'
    klass     = @name.capitalize()
    model     = new App.Models.Group()
    model.url = '/groups/1'
    @partial '.heading', 'shared/heading', model: model
    model.fetch()

class App.Views.Button extends Backbone.View
  tagName: 'button'