/* global $conf */

const fs = require('fs');
const path = require('path');
const apiBuilderConfig = require('@axway/api-builder-config');
const uiConf = require('./config');

function makeIndexPage(filename) {
	return fs.readFileSync(filename).toString()
		.replace(/{{PREFIX}}/g, $conf.prefix)
		.replace(/{{CONFIG}}/g, 'window.$conf = ' + JSON.stringify($conf));
}

function Admin(express, apibuilder, app, config) {
	var indexFile;
	var isDev = false;

	// ADMIN_DIST = "disable hot reloading and use dist instead"
	// If this is enabled make sure you've run a build first.
	if (!process.env.ADMIN_DIST) {
		try {
			fs.statSync(path.join(__dirname, 'src'));
			isDev = true;
		} catch (err) {
			isDev = false;
		}
	}

	global.$conf = {};
	// non-ES6 clone uiConf to global.$conf
	for (let key in uiConf) {
		if (uiConf.hasOwnProperty(key)) {
			global.$conf[key] = uiConf[key];
		}
	}

	$conf.endpointsEnabled = config.endpointsEnabled !== undefined
		? config.endpointsEnabled : $conf.endpointsEnabled;
	$conf.prefix = config.createprefix || $conf.prefix;
	$conf.apiprefix = config.apiprefix || $conf.apiprefix;
	$conf.apiDocPrefix = config.apiDocPrefix || $conf.apiDocPrefix;
	$conf.devMode = isDev;

	$conf.adminRequestLimit
		= (config.admin && config.admin.request && config.admin.request.limit)
		|| $conf.adminRequestLimit || (10 * 1000 * 1000);
	$conf.flags = apiBuilderConfig.flags;

	// Redirect requests from old admin URL
	app.use('/arrow', (req, res, next) => {
		res.redirect($conf.prefix);
		next();
	});

	if (isDev) {
		apibuilder.logger.info('Running API Builder Console in development mode.');
		var webpack = require('webpack'),
			webpackConfig = require('./webpack.config')('dev'),
			webpackDevMiddleware = require('webpack-dev-middleware'),
			compiler = webpack(webpackConfig),
			packedHandler = webpackDevMiddleware(compiler, {
				stats: {
					colors: true,
					// Only log errors and warnings. SAVE THE TERMINAL!
					hash: false,
					version: false,
					timings: false,
					assets: false,
					chunks: false,
					chunkModules: false
				},
				publicPath: webpackConfig.output.publicPath
			});
		this.packedHandler = packedHandler;
		app.use(packedHandler);
		app.use($conf.prefix, express.static(path.join(__dirname, './src')));
		app.use(require('webpack-hot-middleware')(compiler, {
			// eslint-disable-next-line no-console
			log: console.log,
			path: '/console/__webpack_hmr',
			heartbeat: 10 * 1000
		}));

		indexFile = path.join(__dirname, './src/index.tmpl.html');
	} else {
		app.use($conf.prefix, express.static(path.join(__dirname, './dist')));
		indexFile = path.join(__dirname, './dist/index.tmpl.html');
	}

	const indexHtml = makeIndexPage(indexFile);

	app.use((req, resp, next) => {
		// webpack understands that it generated /(prefix)/assets, and that
		// static files can exist in ./src under /(prefix)/*, but it does not
		// understand that /(prefix)/api might be a valid route in the UI.
		// if it starts with '/(prefix)' and has not yet hit a handler, then
		// treat it as static index file.
		if (req.path.endsWith('__webpack_hmr')) {
			resp.set('Content-Type', 'text/event-stream');
			resp.send(indexHtml || '<html></html>');
			return;
		}

		if (req.path.startsWith($conf.prefix)) {
			resp.set('Content-Type', 'text/html');
			resp.send(indexHtml || '<html></html>');
			return;
		}
		next();
	});
}

Admin.prototype.stop = function stopAdminUI(callback) {
	if (this.packedHandler) {
		// give a friendly message that the webpack is busy
		const timeout = setTimeout(() => {
			// eslint-disable-next-line no-console
			console.log('Waiting for webpack to finish before exiting...');
		}, 1000);
		this.packedHandler.waitUntilValid(() => {
			// if not busy, clear the message
			clearTimeout(timeout);
			this.packedHandler.close(callback);
		});
	} else {
		callback();
	}
};

module.exports = Admin;
