var _      = require('lodash'),
    fs     = require('fs'),
    path   = require('path'),
    hbs    = require('express-hbs'),
    api    = require('../api'),
    config = require('../config'),
    errors = require('../errors'),
    themeHandler;

themeHandler = function (blogApp) {
    var handlerMethods = {
        // ### GhostLocals Middleware
        // Expose the standard locals that every external page should have available,
        // separating between the theme and the admin
        ghostLocals: function ghostLocals(req, res, next) {
            // Make sure we have a locals value.
            res.locals = res.locals || {};
            res.locals.version = config.ghostVersion;
            res.locals.safeVersion = config.ghostVersion.match(/^(\d+\.)?(\d+)/)[0];
            // relative path from the URL
            res.locals.relativeUrl = req.path;

            next();
        },

        // ### configHbsForContext Middleware
        // Setup handlebars for the current context (admin or theme)
        configHbsForContext: function configHbsForContext(req, res, next) {
            var themeData = config.theme;
            if (req.secure && config.urlSSL) {
                // For secure requests override .url property with the SSL version
                themeData = _.clone(themeData);
                themeData.url = config.urlSSL.replace(/\/$/, '');
            }

            hbs.updateTemplateOptions({data: {blog: themeData}});

            if (config.paths.themePath && blogApp.get('activeTheme')) {
                blogApp.set('views', path.join(config.paths.themePath, blogApp.get('activeTheme')));
            }

            // Pass 'secure' flag to the view engine
            // so that templates can choose 'url' vs 'urlSSL'
            res.locals.secure = req.secure;

            next();
        },

        // ### Activate Theme
        // Helper for updateActiveTheme
        activateTheme: function activateTheme(activeTheme) {
            var hbsOptions,
                themePartials = path.join(config.paths.themePath, activeTheme, 'partials');

            // clear the view cache
            blogApp.cache = {};

            // set view engine
            hbsOptions = {
                partialsDir: [config.paths.helperTemplates],
                onCompile: function onCompile(exhbs, source) {
                    return exhbs.handlebars.compile(source, {preventIndent: true});
                }
            };

            fs.stat(themePartials, function stat(err, stats) {
                // Check that the theme has a partials directory before trying to use it
                if (!err && stats && stats.isDirectory()) {
                    hbsOptions.partialsDir.push(themePartials);
                }
            });

            blogApp.engine('hbs', hbs.express3(hbsOptions));

            // Update user error template
            errors.updateActiveTheme(activeTheme);

            // Set active theme variable on the express server
            blogApp.set('activeTheme', activeTheme);
        },

        // ### updateActiveTheme
        // Updates the blogApp's activeTheme variable and subsequently
        // activates that theme's views with the hbs templating engine if it
        // is not yet activated.
        updateActiveTheme: function updateActiveTheme(req, res, next) {
            api.settings.read({context: {internal: true}, key: 'activeTheme'}).then(function then(response) {
                var activeTheme = response.settings[0];

                // Check if the theme changed
                if (activeTheme.value !== blogApp.get('activeTheme')) {
                    // Change theme
                    if (!config.paths.availableThemes.hasOwnProperty(activeTheme.value)) {
                        if (!res.isAdmin) {
                            // Throw an error if the theme is not available, but not on the admin UI
                            return errors.throwError('The currently active theme ' + activeTheme.value + ' is missing.');
                        } else {
                            // At this point the activated theme is not present and the current
                            // request is for the admin client.  In order to allow the user access
                            // to the admin client we set an hbs instance on the app so that middleware
                            // processing can continue.
                            blogApp.engine('hbs', hbs.express3());
                            errors.logWarn('The currently active theme "' + activeTheme.value + '" is missing.');

                            return next();
                        }
                    } else {
                        handlerMethods.activateTheme(activeTheme.value);
                    }
                }
                next();
            }).catch(function handleError(err) {
                // Trying to start up without the active theme present, setup a simple hbs instance
                // and render an error page straight away.
                blogApp.engine('hbs', hbs.express3());
                next(err);
            });
        }
    };

    return handlerMethods;
};

module.exports = themeHandler;