require([
  "backbone", "underscore", "jquery", "app",

  //other plain-JS deps

    "datatablesbs3", "bootstrap", "backbonequeryparams"

  ],function(Backbone, _, $, app) {


  // Models come from mongodb
  Backbone.Model.prototype.idAttribute = '_id';

  // http://datatables.net/plug-ins/api#fnSetFilteringDelay
  $.fn.dataTableExt.oApi.fnSetFilteringDelay = function ( oSettings, iDelay ) {
      var _that = this;

      if ( iDelay === undefined ) {
          iDelay = 250;
      }

      this.each( function ( i ) {
          $.fn.dataTableExt.iApiIndex = i;
          var
              $this = this,
              oTimerId = null,
              sPreviousSearch = null,
              anControl = $( 'input', _that.fnSettings().aanFeatures.f );

              anControl.unbind( 'keyup' ).bind( 'keyup', function() {
              var $$this = $this;

              if (sPreviousSearch === null || sPreviousSearch != anControl.val()) {
                  window.clearTimeout(oTimerId);
                  sPreviousSearch = anControl.val();
                  oTimerId = window.setTimeout(function() {
                      $.fn.dataTableExt.iApiIndex = i;
                      _that.fnFilter( anControl.val() );
                  }, iDelay);
              }
          });

          return this;
      } );
      return this;
  };

  $.fn.dataTableExt.oApi.fnReloadAjax = function ( oSettings, sNewSource, fnCallback, bStandingRedraw )
  {
      // DataTables 1.10 compatibility - if 1.10 then versionCheck exists.
      // 1.10s API has ajax reloading built in, so we use those abilities
      // directly.
      if ( $.fn.dataTable.versionCheck ) {
          var api = new $.fn.dataTable.Api( oSettings );

          if ( sNewSource ) {
              api.ajax.url( sNewSource ).load( fnCallback, !bStandingRedraw );
          }
          else {
              api.ajax.reload( fnCallback, !bStandingRedraw );
          }
          return;
      }

      if ( sNewSource !== undefined && sNewSource !== null ) {
          oSettings.sAjaxSource = sNewSource;
      }

      // Server-side processing should just call fnDraw
      if ( oSettings.oFeatures.bServerSide ) {
          this.fnDraw();
          return;
      }

      this.oApi._fnProcessingDisplay( oSettings, true );
      var that = this;
      var iStart = oSettings._iDisplayStart;
      var aData = [];

      this.oApi._fnServerParams( oSettings, aData );

      oSettings.fnServerData.call( oSettings.oInstance, oSettings.sAjaxSource, aData, function(json) {
          /* Clear the old information from the table */
          that.oApi._fnClearTable( oSettings );

          /* Got the data - add it to the table */
          var aData =  (oSettings.sAjaxDataProp !== "") ?
              that.oApi._fnGetObjectDataFn( oSettings.sAjaxDataProp )( json ) : json;

          for ( var i=0 ; i<aData.length ; i++ )
          {
              that.oApi._fnAddData( oSettings, aData[i] );
          }

          oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();

          that.fnDraw();

          if ( bStandingRedraw === true )
          {
              oSettings._iDisplayStart = iStart;
              that.oApi._fnCalculateEnd( oSettings );
              that.fnDraw( false );
          }

          that.oApi._fnProcessingDisplay( oSettings, false );

          /* Callback user function - for event handlers etc */
          if ( typeof fnCallback == 'function' && fnCallback !== null )
          {
              fnCallback( oSettings );
          }
      }, oSettings );
  };

  $(function() {


    // All navigation that is relative should be passed through the navigate
    // method, to be processed by the router. If the link has a `data-bypass`
    // attribute, bypass the delegation completely.
    $(document).on("click", "a:not([data-bypass])", function(evt) {

      // Get the absolute anchor href.
      var href = $(this).attr("href");

      // If the href exists and is a hash route, run it through Backbone.
      if (href && href.indexOf("#") === 0) {
        // Stop the default event to ensure the link will not cause a page
        // refresh.
        evt.preventDefault();

        // `Backbone.history.navigate` is sufficient for all Routers and will
        // trigger the correct events. The Router's internal `navigate` method
        // calls this anyways.  The fragment is sliced from the root.
        Backbone.history.navigate(href, true);
      }
    });

    app.start({
      "container":"#app-container"
    });

    // For easy debug
    window.APP = app;
  });



});
