/* jslint node: true */
'use strict';

//	deps
const bunyan	= require('bunyan');
const paths		= require('path');
const fs		= require('graceful-fs');
const _			= require('lodash');

module.exports = class Log {

	static init() {
		const Config	= require('./config.js').config;
		const logPath	= Config.paths.logs;
		
		const err = this.checkLogPath(logPath);
		if(err) {
			console.error(err.message);	//	eslint-disable-line no-console
			return process.exit();
		}

		const logStreams = [];
		if(_.isObject(Config.logging.rotatingFile)) {
			Config.logging.rotatingFile.path = paths.join(logPath, Config.logging.rotatingFile.fileName);
			logStreams.push(Config.logging.rotatingFile);
		}

		const serializers = {
			err			: bunyan.stdSerializers.err,		//	handle 'err' fields with stack/etc.
		};

		//	try to remove sensitive info by default, e.g. 'password' fields	
		[ 'formData', 'formValue' ].forEach(keyName => {
			serializers[keyName]	= (fd) => Log.hideSensitive(fd); 
		});

		this.log = bunyan.createLogger({
			name			: 'ENiGMA½ BBS',
			streams			: logStreams,
			serializers		: serializers,
		});
	}

	static checkLogPath(logPath) {
		try {
			if(!fs.statSync(logPath).isDirectory()) {
				return new Error(`${logPath} is not a directory`);
			}
			
			return null;
		} catch(e) {
			if('ENOENT' === e.code) {
				return new Error(`${logPath} does not exist`);
			}
			return e;
		}
	}

	static hideSensitive(obj) {
		try {
			//
			//	Use a regexp -- we don't know how nested fields we want to seek and destroy may be
			//
			return JSON.parse(
				JSON.stringify(obj).replace(/"(password|key|authCode)"\s?:\s?"([^"]+)"/, (match, valueName) => {
					return `"${valueName}":"********"`;
				})
			);
		} catch(e) {
			//	be safe and return empty obj!
			return {};
		}
	}
};