/**
 * Copyright 2014 GetHuman LLC
 * Author: Jeff Whelpley
 * Date: 10/21/14
 *
 *
 */
var _ = require('lodash');
var routeHandler;

/**
 * Add web routes
 * @param opts
 */
function addWebRoutes(opts) {
    var server = opts.server;
    var socialProviders = opts.config && opts.config.security && opts.config.security.social;
    var me = this;

    // first add social auth routes
    _.each(socialProviders, function (provider, providerName) {
        server.route({
            method:     ['GET', 'POST'],
            path:       '/auth/' + providerName,
            handler:    me.getWebRouteHandler(opts),
            config:     { auth: providerName }
        });
    });

    routeHandler = this.getWebRouteHandler(opts);

    // all other URLs checked against app config files for dymanic web routes
    server.route({
        method:     '*',
        path:       '/{p*}',
        handler:    routeHandler,
        config: {
            state: {
                parse:      true,
                failAction: 'log'
            }
        }
    });
}

/**
 * The idea here is to use the same request and reply
 * but a different route handler based on the given URL override
 */
function processRoute(opts) {
    if (routeHandler) {
        routeHandler(opts.request, opts.reply, opts.urlOverride);
    }
    else {
        opts.reply.continue();
    }
}

/**
 * Execute the server preprocessing method and return true if the preprocessor
 * handled the request
 *
 * @param request
 * @param reply
 * @returns {Function}
 */
function getServerPreProcessing(request, reply) {
    var me = this;

    return function (routeInfo, page, model) {
        if (!page.serverPreprocessing) { return false; }

        var deps = { request: request, reply: reply, model: model, routeInfo: routeInfo };
        return me.pancakes.cook(page.serverPreprocessing, { dependencies: deps });
    };
}

/**
 * Render the web route for one of the dynamic routes. These routes are based off of
 * the .app config files for each app.
 *
 * @param opts
 */
function getWebRouteHandler(opts) {
    var webRouteHandler = this.pancakes.webRouteHandler;
    var me = this;

    return function handleWebRoute(request, reply, urlOverride) {
        var appName = request.app.name;
        var url = urlOverride || request.url.pathname;
        var routeInfo = webRouteHandler.getRouteInfo(appName, url, request.query, request.app.lang);
        var routeHelper = me.pancakes.cook('routeHelper');

        var newrelic = require('newrelic');
        newrelic.setTransactionName(routeInfo.appName + '||' + routeInfo.lang + '||' + routeInfo.url);

        // if redirect URL exists, just redirect right away
        if (routeInfo.redirect) {

            // make sure tokens in the redirect URL are replaced
            var redirectUrl = routeInfo.redirect;
            _.each(routeInfo.tokens, function (value, key) {
                redirectUrl = redirectUrl.replace('{' + key + '}', value);
            });

            if (redirectUrl.indexOf('{') >= 0) {
                throw new Error('Redirect URL has token that was not replaced: ' + redirectUrl);
            }

            // do full url for all redirects
            if (redirectUrl.indexOf('http') !== 0) {
                redirectUrl = (routeHelper.getBaseUrl(routeInfo.appName) + '') + redirectUrl;
            }

            reply().redirect(redirectUrl).permanent(true);
            return;
        }

        // if the app is handling this request, don't do anything
        if (opts.preProcess && opts.preProcess(request, reply)) { return; }

        var callbacks = {
            serverPreprocessing:    me.getServerPreProcessing(request, reply),
            addToModel:             opts.addToModel,
            pageCacheService:       opts.pageCacheService
        };

        webRouteHandler.processWebRequest(routeInfo, callbacks)
            .then(function (renderedPage) {

                // if no rendered page, it means request was handled earlier somewhere (ex. serverPreprocess redirect)
                if (!renderedPage) {
                    return;
                }

                var response = reply(renderedPage);

                // add content type if in the route info
                if (routeInfo.contentType) {
                    response.header('Content-Type', routeInfo.contentType);
                }

                // as long as the nocache attribute is NOT set, add cache headers (sorry for double negative :-))
                if (!routeInfo.nocache) {
                    response.header('cache-control', 'public, max-age=60');
                }
            })
            .done();    // throw error up to app level error handler
    };
}

module.exports = {
    processRoute: processRoute,
    addWebRoutes: addWebRoutes,
    getWebRouteHandler: getWebRouteHandler,
    getServerPreProcessing: getServerPreProcessing
};
@@ -1298,16 +1298,33 @@
 Override
+, opts.returnCode
 );%0A    %7D
@@ -2229,16 +2229,28 @@
 Override
+, returnCode
 ) %7B%0A    
@@ -4203,16 +4203,40 @@
 redPage)
+.code(returnCode %7C%7C 200)
 ;%0A%0A     

Ensuring return code with 404 and 500