/*
 *  logger.js
 *
 *  David Janes
 *  IOTDB.org
 *  2016-04-07
 *
 *  Copyright [2013-2016] [David P. Janes]
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

"use strict";

const os = require("os")
const util = require("util")
const events = require('events')

/**
 *  Make a new logger. Clevel people could
 *  swap this out to replace it.
 */
const make = _initd => {
    const _ = require("..")
    const self = Object.assign({})

    const initd = _.d.clone(_initd)
    initd.hostname = os.hostname()
    initd.pid = process.pid
    initd.v = 0

    const emitter = new events();
    self.on = (...rest) => emitter.on.apply(emitter, rest)

    const _log = level => (...rest) => {
        let packet = _.d.clone(initd)
        packet.level = level;
        packet.time = _.timestamp.make()

        if (rest.length) {
            if (rest[0] instanceof Error) {
                packer.err = {
                    name: error.name,
                    message: error.message,
                    stack: error.stack,
                }

                rest.shift()
            } else if (_.is.Object(rest[0])) {
                packet = Object.assign({}, packet, rest[0])
                rest.shift()
            }
        }

        if (rest.length) {
            packet.msg = util.format.apply(util.format, rest)
        }

        process.stdout.write(JSON.stringify(packet))
        process.stdout.write("\n")

        emitter.emit("event", packet)

        return packet;
    }

    self.trace = _log(10)
    self.debug = _log(20)
    self.info = _log(30)
    self.warn = _log(40)
    self.error = _log(50)
    self.fatal = _log(60)

    return self;
};

const _logd = {
    debug: true,
    info: true,
    error: true,
    warn: true,
    trace: true,
    fatal: true,
};

/**
 *  Set the logging levels.
 *
 *  If d.all is set, everything in _logd
 *  is set to that value first.
 */
const levels = d => {
    if (d.all !== undefined) {
        _.keys(_logd).forEach(key => _logd[key] = d.all);
    } 

    _.mapObject(d).forEach(kv => _logd[kv[0]] = kv[1])
};

/**
 *  Turn off all logging except
 *  for fatal error messages
 */
const silent = function() {
    levels({
        all: false,
        fatal: true,
    });
};

const _mutes = [];

/**
 *  Mute based on dictionary
 */
const mute = md => _mutes.push(md);

/**
 *  Create a logger. If you don't want
 *  to use bunyan, replace 'logger.make',
 *  not this
 */
const logger = function (initd) {
    const _d = require("./d").d;
    const _logger = function() {
        let l = null;

        const _make = () => {
            if (l === null) {
                l = make(initd);
            }
        };

        const _level = level => {
            return function(...rest) {
                if (!_logd[level]) {
                    return;
                }

                if (_mutes.find(m => _d.is.subset(m, initd))) {
                    return;
                }

                _make();
                return l[level](...rest)
            }
        };

        return {
            debug: _level("debug"),
            info: _level("info"),
            warn: _level("warn"),
            error: _level("error"),
            trace: _level("trace"),
            fatal: _level("fatal"),
        }
    };

    return _logger();
};

/* --- API --- */
exports.logger = {
    make: make,
    logger: logger,
    levels: levels,
    silent: silent,
    mute: mute,
};

@@ -2341,16 +2341,21 @@
 %0A *  If 
+level
 d.all is
@@ -2431,16 +2431,21 @@
 evels = 
+level
 d =%3E %7B%0A 
@@ -2451,16 +2451,21 @@
     if (
+level
 d.all !=
@@ -2487,17 +2487,22 @@
         
-_
+Object
 .keys(_l
@@ -2534,16 +2534,21 @@
 %5Bkey%5D = 
+level
 d.all);%0A
@@ -2556,27 +2556,31 @@
    %7D
- 
 %0A%0A    
-_.map
 Object
-(
+.keys(level
 d).f
@@ -2587,17 +2587,18 @@
 orEach(k
-v
+ey
  =%3E _log
@@ -2604,25 +2604,28 @@
 gd%5Bk
-v%5B0%5D%5D = kv%5B1
+ey%5D = leveld%5Bkey
 %5D)%0A%7D
-;
 %0A%0A/*

fix logging levels (sorta)