'use strict';

// -- Configure JavaScript Runtime ---------------------------------------------

var hasNativeIntl    = !!global.Intl;
var hasNativePromise = !!global.Promise;

require('es6-shim');

hasNativeIntl    || (global.Intl = require('intl'));
hasNativePromise || (global.Promise = require('promise'));

global.React          = require('react/addons');
global.ReactIntl      = require('react-intl');
global.Handlebars     = require('handlebars');
global.HandlebarsIntl = require('handlebars-intl');
global.dust           = require('dustjs-linkedin');
global.DustIntl       = require('dust-intl');

// -----------------------------------------------------------------------------

var path     = require('path'),
    express  = require('express'),
    expstate = require('express-state'),
    reverend = require('reverend');

var config     = require('./config'),
    hbs        = require('./lib/hbs'),
    middleware = require('./middleware'),
    routes     = require('./routes');

DustIntl.registerWith(dust);

// -- Configure Express App ----------------------------------------------------

var app = module.exports = express();

expstate.extend(app);

app.set('name', 'FormatJS');
app.set('port', config.port);
app.set('available locales', config.availableLocales);
app.set('default locale', 'en-US');
app.set('state namespace', 'APP');

app.enable('strict routing');
app.enable('case sensitive routing');

app.engine(hbs.extname, hbs.engine);
app.set('view engine', hbs.extname);
app.set('views', config.dirs.views);

if (app.get('env') === 'development') {
    // This will watch files during development and automattically re-build.
    app.watcher = require('./lib/watcher');
}

// -- Middleware ---------------------------------------------------------------

var router = express.Router({
    caseSensitive: app.get('case sensitive routing'),
    strict       : app.get('strict routing')
});

if (app.get('env') === 'development') {
    app.use(middleware.logger('tiny'));
}

app.use(middleware.compress());
app.use(middleware.favicon(path.join('./public/favicon.ico')));
app.use(middleware.static(path.join(config.dirs.build, 'client'), {maxage: '1m'}));
app.use(router);
app.use(middleware.slash());

// -- Routes -------------------------------------------------------------------

var route = router.route.bind(router);

router.use(middleware.fixBadSafari);
router.use(middleware.intl);

routes.home(route('/'));
routes.about(route('/about/'));
routes.guide(route('/guide/'));
routes.integrations(route('/integrations/'));
routes.github(route('/github/'));

routes.react(route('/react/'));
routes.ember(route('/ember/'));
routes.handlebars(route('/handlebars/'));
routes.dust(route('/dust/'));

app.getRoute = function (routeName) {
    var layer = router.stack.find(function (layer) {
        return layer.route && layer.route.name === routeName;
    });

    if (!layer) {
        throw new Error('No route name: ' + routeName);
    }

    return layer.route;
};

app.getPathTo = function (routeName, context) {
    return reverend(app.getRoute(routeName).path, context);
};

// -- Locals -------------------------------------------------------------------

Object.assign(app.locals, {
    brand  : app.get('name'),
    tagline: 'Internationalize your web apps on the client & server.',

    min: app.get('env') === 'production' ? '.min' : '',

    menuItems    : ['guide', 'integrations', 'github'].map(app.getRoute),
    footMenuItems: ['home', 'about', 'guide', 'integrations', 'github'].map(app.getRoute),

    helpers: {
        pathTo: function (name, options) {
            return app.getPathTo(name, options.hash);
        }
    }
});

if (app.get('env') === 'production') {
    app.locals.analytics = config.ga;
}

@@ -1,16 +1,83 @@
-'use strict'
+/* global Intl, IntlPolyfill */%0A'use strict';%0A%0Avar config = require('./config')
 ;%0A%0A/
@@ -263,29 +263,457 @@
 );%0A%0A
-hasNativeIntl    %7C%7C (
+// es6-shim provides a Promise implementation, but it's not very good.%0AhasNativePromise %7C%7C (global.Promise = require('promise'));%0A%0A// Determine if the native %60Intl%60 has the locale data we need.%0Avar hasNativeLocaleData = hasNativeIntl &&%0A    config.availableLocales.every(function (locale) %7B%0A        return Intl.NumberFormat.supportedLocalesOf(locale)%5B0%5D === locale;%0A    %7D);%0A%0Aif (!hasNativeIntl) %7B%0A    // No %60Intl%60, so use and load the polyfill.%0A    
 glob
@@ -741,69 +741,405 @@
 tl')
-)
 ;%0A
-hasNativePromise %7C%7C (global.Promise = require('promise'));
+%7D else if (!hasNativeLocaleData) %7B%0A    // %60Intl%60 exists, but it doesn't have the data we need, so load the polyfill%0A    // and replace the constructors with need with the polyfill's.%0A    require('intl');%0A    Intl.NumberFormat   = IntlPolyfill.NumberFormat;%0A    Intl.DateTimeFormat = IntlPolyfill.DateTimeFormat;%0A%7D%0A%0A// -- FormatJS Libs ------------------------------------------------------------
 %0A%0Agl
@@ -1426,24 +1426,68 @@
 st-intl');%0A%0A
+global.DustIntl.registerWith(global.dust);%0A%0A
 // ---------
@@ -1586,21 +1586,21 @@
 ('path')
-,%0A   
+;%0Avar
  express
@@ -1621,21 +1621,21 @@
 xpress')
-,%0A   
+;%0Avar
  expstat
@@ -1662,21 +1662,21 @@
 -state')
-,%0A   
+;%0Avar
  reveren
@@ -1709,46 +1709,8 @@
 var 
-config     = require('./config'),%0A    
 hbs 
@@ -1738,21 +1738,21 @@
 ib/hbs')
-,%0A   
+;%0Avar
  middlew
@@ -1780,21 +1780,21 @@
 leware')
-,%0A   
+;%0Avar
  routes 
@@ -1825,38 +1825,8 @@
 );%0A%0A
-DustIntl.registerWith(dust);%0A%0A
 // -

Determine when to load Intl Polyfill on server