text: // Node.js core dependencies
  const path = require('path')
  
  // Npm dependencies
  const express = require('express')
  const cookieSession = require('cookie-session')
  const favicon = require('serve-favicon')
  const bodyParser = require('body-parser')
  const i18n = require('i18n')
  const logger = require('./common/utils/logger')
  const loggingMiddleware = require('morgan')
  const argv = require('minimist')(process.argv.slice(2))
  const staticify = require('staticify')(path.join(__dirname, 'public'))
  const compression = require('compression')
  const nunjucks = require('nunjucks')
  const Sequelize = require('sequelize')
  const helmet = require('helmet')
  
  
  // Local dependencies
  const router = require('./app/router')
  const noCache = require('./common/utils/no-cache')
  const correlationHeader = require('./common/middleware/correlation-header')
  
  // Global constants
  const unconfiguredApp = express()
  const oneYear = 86400000 * 365
  const publicCaching = {maxAge: oneYear}
  const PORT = (process.env.PORT || 3000)
  const {NODE_ENV} = process.env
  const CSS_PATH = staticify.getVersionedPath('/stylesheets/application.min.css')
  const JAVASCRIPT_PATH = staticify.getVersionedPath('/javascripts/application.js')
  const GA_ID = (process.env.GA_ID || '')
  const COOKIE_SECRET = (process.env.COOKIE_SECRET || '')
  const BASE_URL = (process.env.BASE_URL || '')
  
  // Define app views
  const APP_VIEWS = [
    path.join(__dirname, '/govuk_modules/govuk_template/views/layouts'),
    __dirname
  ]
  
  function initialiseGlobalMiddleware(app) {
    app.set('settings', {getVersionedPath: staticify.getVersionedPath})
    app.use(favicon(path.join(__dirname, 'govuk_modules', 'govuk_template', 'assets', 'images', 'favicon.ico')))
    app.use(compression())
    app.use(staticify.middleware)
  
    if (process.env.DISABLE_REQUEST_LOGGING !== 'true') {
      app.use(/\/((?!images|public|stylesheets|javascripts).)*/, loggingMiddleware(
        ':remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent" - total time :response-time ms'))
    }
  
    app.use((req, res, next) => {
      res.locals.asset_path = '/public/' // eslint-disable-line camelcase
      noCache(res)
      next()
    })
    app.use(bodyParser.json())
    app.use(bodyParser.urlencoded({extended: true}))
    app.use(helmet())
    app.use('*', correlationHeader)
  }
  
  function initialiseI18n(app) {
    i18n.configure({
      locales: ['en'],
      directory: path.join(__dirname, '/locales'),
      objectNotation: true,
      defaultLocale: 'en',
      register: global
    })
    app.use(i18n.init)
  }
  
  function initialiseProxy(app) {
    app.enable('trust proxy')
  }
  
  function initialiseTemplateEngine(app) {
    // Configure nunjucks
    // see https://mozilla.github.io/nunjucks/api.html#configure
    const nunjucksConfiguration = {
      express: app, // The express app that nunjucks should install to
      autoescape: true, // Controls if output with dangerous characters are escaped automatically
      throwOnUndefined: false, // Throw errors when outputting a null/undefined value
      trimBlocks: true, // Automatically remove trailing newlines from a block/tag
      lstripBlocks: true, // Automatically remove leading whitespace from a block/tag
      watch: false, // Reload templates when they are changed (server-side). To use watch, make sure optional dependency chokidar is installed
      noCache: NODE_ENV !== 'production' // Never use a cache and recompile templates each time (server-side)
    }
  
    // Initialise nunjucks environment
    const nunjucksEnvironment = nunjucks.configure(APP_VIEWS, nunjucksConfiguration)
  
    // Set view engine
    app.set('view engine', 'njk')
  
    // Version static assets on production for better caching
    // if it's not production we want to re-evaluate the assets on each file change
    nunjucksEnvironment.addGlobal('css_path', NODE_ENV === 'production' ? CSS_PATH : staticify.getVersionedPath('/stylesheets/application.min.css'))
    nunjucksEnvironment.addGlobal('js_path', NODE_ENV === 'production' ? JAVASCRIPT_PATH : staticify.getVersionedPath('/javascripts/application.js'))
    nunjucksEnvironment.addGlobal('ga_id', GA_ID)
    nunjucksEnvironment.addGlobal('base_url', BASE_URL)
  }
  
  function initialisePublic(app) {
    app.use('/javascripts', express.static(path.join(__dirname, '/public/assets/javascripts'), publicCaching))
    app.use('/images', express.static(path.join(__dirname, '/public/images'), publicCaching))
    app.use('/stylesheets', express.static(path.join(__dirname, '/public/assets/stylesheets'), publicCaching))
    app.use('/public', express.static(path.join(__dirname, '/public')))
    app.use('/public', express.static(path.join(__dirname, '/govuk_modules/govuk_frontend_toolkit')))
    app.use('/public', express.static(path.join(__dirname, '/govuk_modules/govuk_template/assets')))
  }
  
  function initialiseCookie(app) {
    app.use(cookieSession({
      name: 'co_facility_time',
      keys: [COOKIE_SECRET],
      maxAge: 24 * 60 * 60 * 500, // 12 hours
      httpOnly: true
    }))
  }
  
  function initialiseRoutes(app) {
    router.bind(app)
  }
  
  function initialiseErrorHandling(app) {
    app.use(function(req, res, next){
      res.redirect('/error/404');
    });
  }
  
  function listen() {
    const app = initialise()
    app.listen(PORT)
    logger.info('Listening on port ' + PORT)
  }
  
  /**
   * Configures app
   * @return app
   */
  function initialise() {
    const app = unconfiguredApp
    app.disable('x-powered-by')
    initialiseProxy(app)
    initialiseI18n(app)
    initialiseGlobalMiddleware(app)
    initialiseCookie(app)
    initialiseTemplateEngine(app)
    initialiseRoutes(app)
    initialisePublic(app)
    initialiseErrorHandling(app)
    return app
  }
  
  /**
   * Starts app after ensuring DB is up
   */
  function start() {
    listen()
  }
  
  /**
   * -i flag. Immediately invoke start.
   * Allows script to be run by task runner
   */
  if (argv.i) {
    start()
  }
  
  module.exports = {
    start,
    getApp: initialise,
    staticify
  }
  