var async = require('async'),
    child_process = require('child_process'),
    config = require('./config'),
    fs = require('fs'),
    imagerConfig = require('./imager/config'),
    reportConfig = require('./report/config'),
    streamBuffers = require('stream-buffers'),
    util = require('util');

function make_client(inputs, out, cb) {

var defines = {};
for (var k in config)
	defines[k] = JSON.stringify(config[k]);
for (var k in imagerConfig)
	defines[k] = JSON.stringify(imagerConfig[k]);
for (var k in reportConfig)
	defines[k] = JSON.stringify(reportConfig[k]);

// UGH
var configDictLookup = {
	config: config,
	imagerConfig: imagerConfig,
	reportConfig: reportConfig,
};

function lookup_config(dictName, key) {
	var dict = configDictLookup[dictName];
	if (key.indexOf('SECURE') >= 0 || key.indexOf('PRIVATE') >= 0)
		throw new Error("Refusing " + key + " in client code!");
	return dict[key];
}

var config_re = /\b(\w+onfig)\.(\w+)\b/;

function convert(file, cb) {
	if (/^lib\//.test(file))
		return cb("lib/* should be in VENDOR_DEPS");
	if (/^config\.js/.test(file))
		return cb("config.js shouldn't be in client");

fs.readFile(file, 'UTF-8', function (err, fullFile) {
	if (err)
		return cb(err);

	var lines = fullFile.split('\n');
	var waitForDrain = false;
	for (var j = 0; j < lines.length; j++) {
		var line = lines[j];
		if (/^var\s+DEFINES\s*=\s*exports\s*;\s*$/.test(line))
			continue;
		if (/^var\s+(\w+onfig|common|_)\s*=\s*require.*$/.test(line))
			continue;
		m = line.match(/^DEFINES\.(\w+)\s*=\s*(.+);$/);
		if (m) {
			defines[m[1]] = m[2];
			continue;
		}
		m = line.match(/^exports\.(\w+)\s*=\s*(\w+)\s*;\s*$/);
		if (m && m[1] == m[2])
			continue;
		m = line.match(/^exports\.(\w+)\s*=\s*(.*)$/);
		if (m)
			line = 'var ' + m[1] + ' = ' + m[2];

		// XXX: risky
		line = line.replace(/\bcommon\.\b/g, '');

		while (true) {
			var m = line.match(config_re);
			if (!m)
				break;
			var cfg = lookup_config(m[1], m[2]);
			if (cfg === undefined) {
				return cb("No such "+m[1]+" var "+m[2]);
			}
			// Bleh
			if (cfg instanceof RegExp)
				cfg = cfg.toString();
			else
				cfg = JSON.stringify(cfg);
			line = line.replace(config_re, cfg);
		}
		for (var src in defines) {
			if (line.indexOf(src) < 0)
				continue;
			var regexp = new RegExp('(?:DEFINES\.)?\\b' + src
					+ '\\b', 'g');
			line = line.replace(regexp, defines[src]);
		}
		waitForDrain = !out.write(line+'\n', 'UTF-8');
	}
	if (waitForDrain)
		out.once('drain', function () { cb(null); });
	else
		cb(null);

}); // readFile
}

	// kick off
	async.eachSeries(inputs, convert, cb);
};

exports.make_client = make_client;

function make_minified(files, out, cb) {
	var buf = new streamBuffers.WritableStreamBuffer();
	buf.once('error', cb);
	make_client(files, buf, function (err) {
		if (err)
			return cb(err);
		var src = buf.getContentsAsString('utf-8');
		if (!src || !src.length)
			return cb('make_minified: no client JS was generated');
		minify(src);
	});

	function minify(src) {
		var UglifyJS = require('uglify-es');
		var ugly;
		try {
			ugly = UglifyJS.minify(src, {
				mangle: false,
			});
		}
		catch (e) {
			return cb(e);
		}
		out.write(ugly.code, cb);
	}
};

exports.make_minified = make_minified;

function make_maybe_minified(files, out, cb) {
	if (config.DEBUG)
		make_client(files, out, cb);
	else
		make_minified(files, out, cb);
}

exports.make_maybe_minified = make_maybe_minified;

if (require.main === module) {
	var files = [];
	for (var i = 2; i < process.argv.length; i++) {
		var arg = process.argv[i];
		if (arg[0] != '-') {
			files.push(arg);
			continue;
		}
		else {
			util.error('Unrecognized option ' + arg);
			process.exit(1);
		}
	}

	make_maybe_minified(files, process.stdout, function (err) {
		if (err) throw err;
	});
}
