var Promise = require( 'bluebird' ),
    Checkit = require( 'checkit' ),
    express = require( 'express' ),
    _ = require( 'lodash' ),
    NotFoundError = require( '../errors/not-found' ),
    InvalidRequestError = require( '../errors/invalid-request' ),
    bookshelf = require( 'bookshelf' ).bookshelf,
    http = require( '../helpers/promisify-http' ),
    auth = require( '../middlewares/auth' );

var BaseController = module.exports = function( module ) {
    this.module = module;
    this.routes = this.getRoutes();
    this.injectAuthMiddleware();
    this.assignRouteHandlers();
};

BaseController.prototype.getRoutes = function() {
    return {
        index: { method: 'GET', path: '/', middlewares: [] },
        show: { method: 'GET', path: '/:id', middlewares: [] },
        store: { method: 'POST', path: '/', middlewares: [] },
        update: { method: 'PUT', path: '/:id', middlewares: [] },
        patch: { method: 'PATCH', path: '/:id', middlewares: [] },
        delete: { method: 'DELETE', path: '/:id', middlewares: [] }
    };
};

BaseController.prototype.Model = bookshelf.Model;

BaseController.prototype.authorize = false;

BaseController.prototype.injectAuthMiddleware = function() {
    if ( true === this.authorize ) {
        this.authorize = Object.keys( this.routes );
    }

    if ( this.authorize instanceof Array ) {
        var routes = this.routes;
        this.authorize.forEach(function( route ) {
            routes[ route ].middlewares.unshift( auth );
        });
    }
};

BaseController.prototype.assignRouteHandlers = function() {
    var _this = this;

    this.router = express.Router();

    for ( var route in this.routes ) {
        var routeOptions = this.routes[ route ],
            method = routeOptions.method.toLowerCase();

        var middlewares = routeOptions.middlewares.map(function( middleware ) {
            return middleware.bind( _this );
        });

        middlewares.push( http( this[ route ].bind( this ) ) );
        this.router[ method ].apply( this.router, [ routeOptions.path ].concat( middlewares ) );
    }
};

BaseController.prototype.generateResponse = function( response ) {
    var responseKey;
    if ( response instanceof bookshelf.Collection ) {
        responseKey = this.Model.prototype.tableName;
    } else {
        responseKey = this.module;
    }

    return _.object([ [ responseKey, response ] ])
};

BaseController.prototype.index = function() {
    return this.Model.fetchAll().then( this.generateResponse.bind( this ) );
};

BaseController.prototype.show = function( body, options ) {
    var model = new this.Model();

    return model
        .query( 'where', model.idAttribute, '=', options.id )
        .fetch({ require: true })
        .then( this.generateResponse.bind( this ) )
        .catch( this.Model.NotFoundError, function() {
            return Promise.reject( new NotFoundError() );
        });
};

BaseController.prototype.store = function( body, options ) {
    return new this.Model()
        .save( body )
        .then( this.generateResponse.bind( this ) )
        .catch( Checkit.Error, function() {
            return Promise.reject( new InvalidRequestError( 'The request syntax was malformed' ) );
        });
};

BaseController.prototype.update = function( body, options ) {
    var model = new this.Model();

    return model
        .query( 'where', model.idAttribute, '=', options.id )
        .fetch({ require: true })
        .then(function( resource ) {
            return resource.save( body );
        })
        .catch( this.Model.NotFoundError, function() {
            return Promise.reject( new NotFoundError() );
        });
};

BaseController.prototype.patch = function( body, options ) {
    var model = new this.Model();

    return model
        .query( 'where', model.idAttribute, '=', options.id )
        .fetch({ require: true })
        .then(function( resource ) {
            return resource.save( body, { patch: true });
        })
        .then( this.generateResponse.bind( this ) )
        .catch( this.Model.NotFoundError, function() {
            return Promise.reject( new NotFoundError() );
        });
};

BaseController.prototype.delete = function( body, options ) {
    var model = new this.Model();

    return model
        .query( 'where', model.idAttribute, '=', options.id )
        .fetch({ require: true })
        .then(function( resource ) {
            return resource.destroy();
        })
        .catch( this.Model.NotFoundError, function() {
            return Promise.reject( new NotFoundError() );
        });
};
@@ -1791,26 +1791,8 @@
     
- var middlewares =
  rou
@@ -1805,115 +1805,8 @@
 ons.
-middlewares.map(function( middleware ) %7B%0A            return middleware.bind( _this );%0A        %7D);%0A%0A        
 midd
@@ -1937,16 +1937,29 @@
 concat( 
+routeOptions.
 middlewa

Remove this-binding on base controller route middlewares