text: /**
   * Module dependencies.
   */
  
  var _ = require('underscore');
  var express = require('express');
  var cookieParser = require('cookie-parser');
  var compress = require('compression');
  var session = require('express-session');
  var bodyParser = require('body-parser');
  var logger = require('morgan');
  var errorHandler = require('errorhandler');
  var csrf = require('lusca').csrf();
  var methodOverride = require('method-override');
  
  var MongoStore = require('connect-mongo')({ session: session });
  var flash = require('express-flash');
  var path = require('path');
  var mongoose = require('mongoose');
  var passport = require('passport');
  var expressValidator = require('express-validator');
  var connectAssets = require('connect-assets');
  
  /**
   * Load controllers.
   */
  
  var homeController = require('./controllers/home');
  var userController = require('./controllers/user');
  var apiController = require('./controllers/api');
  var contactController = require('./controllers/contact');
  var scheduleController = require('./controllers/schedule');
  var courseController = require('./controllers/course');
  
  /**
   * API keys + Passport configuration.
   */
  
  var secrets = require('./config/secrets');
  var passportConf = require('./config/passport');
  
  /**
   * Create Express server.
   */
  
  var app = express();
  
  /**
   * Mongoose configuration.
   */
  
  mongoose.connect(secrets.db);
  mongoose.connection.on('error', function() {
    console.error('✗ MongoDB Connection Error. Please make sure MongoDB is running.');
  });
  
  /**
   * Express configuration.
   */
  
  var hour = 3600000;
  var day = hour * 24;
  var week = day * 7;
  
  var csrfWhitelist = [
    '/this-url-will-bypass-csrf'
  ];
  
  app.set('port', process.env.PORT || 3000);
  app.set('views', path.join(__dirname, 'views'));
  app.set('view engine', 'jade');
  app.use(connectAssets({
    paths: ['public/css', 'public/js'],
    helperContext: app.locals
  }));
  app.use(compress());
  app.use(logger('dev'));
  app.use(bodyParser.json());
  app.use(bodyParser.urlencoded());
  app.use(expressValidator());
  app.use(methodOverride());
  app.use(cookieParser());
  app.use(session({
    secret: secrets.sessionSecret,
    store: new MongoStore({
      url: secrets.db,
      auto_reconnect: true
    })
  }));
  app.use(passport.initialize());
  app.use(passport.session());
  app.use(function(req, res, next) {
    // Conditional CSRF.
    if (_.contains(csrfWhitelist, req.path)) return next();
    csrf(req, res, next);
  });
  app.use(function(req, res, next) {
    res.locals.user = req.user;
    next();
  });
  app.use(flash());
  app.use(express.static(path.join(__dirname, 'public'), { maxAge: week }));
  app.use(function(req, res, next) {
    // Keep track of previous URL to redirect back to
    // original destination after a successful login.
    if (req.method !== 'GET') return next();
    var path = req.path.split('/')[1];
    if (/(auth|login|logout|signup)$/i.test(path)) return next();
    req.session.returnTo = req.path;
    next();
  });
  
  /**
   * Application routes.
   */
  
  app.get('/', homeController.index);
  app.get('/schedule/create', scheduleController.create);
  app.get('/schedule', scheduleController.interact);
  app.get('/login', userController.getLogin);
  app.post('/login', userController.postLogin);
  app.get('/logout', userController.logout);
  app.get('/forgot', userController.getForgot);
  app.post('/forgot', userController.postForgot);
  app.get('/reset/:token', userController.getReset);
  app.post('/reset/:token', userController.postReset);
  app.get('/signup', userController.getSignup);
  app.post('/signup', userController.postSignup);
  app.get('/contact', contactController.getContact);
  app.post('/contact', contactController.postContact);
  app.get('/account', passportConf.isAuthenticated, userController.getAccount);
  app.post('/account/profile', passportConf.isAuthenticated, userController.postUpdateProfile);
  app.post('/account/password', passportConf.isAuthenticated, userController.postUpdatePassword);
  app.post('/account/delete', passportConf.isAuthenticated, userController.postDeleteAccount);
  app.get('/account/unlink/:provider', passportConf.isAuthenticated, userController.getOauthUnlink);
  app.post('/course/create', courseController.create);
  //app.post('/course/convert_classification', courseController.convertClassification);
  app.get('/api', apiController.getApi);
  app.get('/api/lastfm', apiController.getLastfm);
  app.get('/api/nyt', apiController.getNewYorkTimes);
  app.get('/api/aviary', apiController.getAviary);
  app.get('/api/steam', apiController.getSteam);
  app.get('/api/stripe', apiController.getStripe);
  app.post('/api/stripe', apiController.postStripe);
  app.get('/api/scraping', apiController.getScraping);
  app.get('/api/twilio', apiController.getTwilio);
  app.post('/api/twilio', apiController.postTwilio);
  app.get('/api/clockwork', apiController.getClockwork);
  app.post('/api/clockwork', apiController.postClockwork);
  app.get('/api/foursquare', passportConf.isAuthenticated, passportConf.isAuthorized, apiController.getFoursquare);
  app.get('/api/tumblr', passportConf.isAuthenticated, passportConf.isAuthorized, apiController.getTumblr);
  app.get('/api/facebook', passportConf.isAuthenticated, passportConf.isAuthorized, apiController.getFacebook);
  app.get('/api/github', passportConf.isAuthenticated, passportConf.isAuthorized, apiController.getGithub);
  app.get('/api/twitter', passportConf.isAuthenticated, passportConf.isAuthorized, apiController.getTwitter);
  app.get('/api/venmo', passportConf.isAuthenticated, passportConf.isAuthorized, apiController.getVenmo);
  app.post('/api/venmo', passportConf.isAuthenticated, passportConf.isAuthorized, apiController.postVenmo);
  app.get('/api/linkedin', passportConf.isAuthenticated, passportConf.isAuthorized, apiController.getLinkedin);
  app.get('/api/instagram', passportConf.isAuthenticated, passportConf.isAuthorized, apiController.getInstagram);
  
  /**
   * OAuth routes for sign-in.
   */
  
  app.get('/auth/instagram', passport.authenticate('instagram'));
  app.get('/auth/instagram/callback', passport.authenticate('instagram', { failureRedirect: '/login' }), function(req, res) {
    res.redirect(req.session.returnTo || '/');
  });
  app.get('/auth/facebook', passport.authenticate('facebook', { scope: ['email', 'user_location'] }));
  app.get('/auth/facebook/callback', passport.authenticate('facebook', { failureRedirect: '/login' }), function(req, res) {
    res.redirect(req.session.returnTo || '/');
  });
  app.get('/auth/github', passport.authenticate('github'));
  app.get('/auth/github/callback', passport.authenticate('github', { failureRedirect: '/login' }), function(req, res) {
    res.redirect(req.session.returnTo || '/');
  });
  app.get('/auth/google', passport.authenticate('google', { scope: 'profile email' }));
  app.get('/auth/google/callback', passport.authenticate('google', { failureRedirect: '/login' }), function(req, res) {
    res.redirect(req.session.returnTo || '/');
  });
  app.get('/auth/twitter', passport.authenticate('twitter'));
  app.get('/auth/twitter/callback', passport.authenticate('twitter', { failureRedirect: '/login' }), function(req, res) {
    res.redirect(req.session.returnTo || '/');
  });
  app.get('/auth/linkedin', passport.authenticate('linkedin', { state: 'SOME STATE' }));
  app.get('/auth/linkedin/callback', passport.authenticate('linkedin', { failureRedirect: '/login' }), function(req, res) {
    res.redirect(req.session.returnTo || '/');
  });
  
  /**
   * OAuth routes for API examples that require authorization.
   */
  
  app.get('/auth/foursquare', passport.authorize('foursquare'));
  app.get('/auth/foursquare/callback', passport.authorize('foursquare', { failureRedirect: '/api' }), function(req, res) {
    res.redirect('/api/foursquare');
  });
  app.get('/auth/tumblr', passport.authorize('tumblr'));
  app.get('/auth/tumblr/callback', passport.authorize('tumblr', { failureRedirect: '/api' }), function(req, res) {
    res.redirect('/api/tumblr');
  });
  app.get('/auth/venmo', passport.authorize('venmo', { scope: 'make_payments access_profile access_balance access_email access_phone' }));
  app.get('/auth/venmo/callback', passport.authorize('venmo', { failureRedirect: '/api' }), function(req, res) {
    res.redirect('/api/venmo');
  });
  
  /**
   * 500 Error Handler.
   * As of Express 4.0 it must be placed at the end of all routes.
   */
  
  app.use(errorHandler());
  
  /**
   * Start Express server.
   */
  
  app.listen(app.get('port'), function() {
    console.log("✔ Express server listening on port %d in %s mode", app.get('port'), app.get('env'));
  });
  
  module.exports = app;
  