import bunyan from 'bunyan';
import { forEach } from 'lodash';

import scrub from './util/common/scrub';
import { assembleConfig, toBunyanConfig, BUNYAN_LOGGER_LEVELS } from './util/common/config';

import ClientConsoleLogger from './util/client/consoleLogger';
import ClientLogentriesLogger from './util/client/logentriesLogger';
import ClientRollbarLogger, { isGlobalRollbarConfigured } from './util/client/rollbarLogger';

/**
 * A logger than can be used in browsers
 * @param   {Object} config
 * @returns {Object} - a preconfigured `bunyan` logger instance
 */
export default function ClientLogger(config = {}) {
  const clientConfig = assembleConfig(config, getStreams);
  const logger = bunyan.createLogger(toBunyanConfig(clientConfig));

  // Attach a few extras to instances of ClientLogger
  logger.config = config;

  return logger;
}

// Extend child function to give _emit access to config in log children
const originalChild = bunyan.prototype.child;
bunyan.prototype.child = function(options, simple) {
  const childLogger = originalChild.call(this, options, simple);
  childLogger.config = this.config;
  return childLogger;
}

// Overwrite logger functions to scrub out all fields, including pre stringified msg
forEach(BUNYAN_LOGGER_LEVELS, (type) => {
  const original = bunyan.prototype[type];
  bunyan.prototype[type] = function(...args) {
    const newArgs = args.map((arg) => scrub(arg, this.config));
    return original.apply(this, newArgs);
  }
});

/**
 * Add standard Client logger streams to `config.streams`
 * @private
 * @param  {Object} config
 * @param  {Array?} config.streams
 * @returns {Array}
 */
function getStreams(config) {
  // Any passed in streams
  const streams = Array.isArray(config.streams)
    ? [...config.streams]
    : [];

  // Nice console output
  if (config.stdout) {
    streams.push({
      name: 'stdout',
      level: config.level,
      stream: new ClientConsoleLogger(),
      type: 'raw'
    });
  }

  // Rollbar Transport
  // Messages at the warn level or higher are transported to Rollbar
  // Detects presence of global Rollbar and passed in token
  if (isGlobalRollbarConfigured()) {
    if (config.rollbarToken) {
      streams.push({
        name: 'rollbar',
        level: 'warn',
        stream: new ClientRollbarLogger({
          token: config.rollbarToken,
          environment: config.environment,
          codeVersion: config.codeVersion,
        }),
        type: 'raw'
      });
    }
  } else {
    /* eslint-disable no-console */
    console.warn('Client rollbar is not correctly configured');
    /* eslint-enable */
  }

  // Transport client logs
  if (config.logentriesToken) {
    streams.push({
      name: 'logentries',
      level: config.level,
      stream: new ClientLogentriesLogger({ token: config.logentriesToken }),
      type: 'raw'
    });
  }

  return streams;
}

@@ -1,12 +1,27 @@
+'use strict';%0A%0A
 import bunya
@@ -41,55 +41,27 @@
 n';%0A
+%0A
 import 
-%7B forEach %7D from 'lodash';%0A%0Aimport scrub
+logForLevel
  fro
@@ -77,21 +77,27 @@
 /common/
-scrub
+logForLevel
 ';%0Aimpor
@@ -469,32 +469,55 @@
 param   %7BObject%7D
+  config - we-js-logger
  config%0A * @retu
@@ -516,23 +516,23 @@
  * @
-returns
+param  
  %7BObject
 %7D - 
@@ -531,52 +531,150 @@
 ject
+?
 %7D 
-- a preconfigured %60bunyan%60 logger instance
+logger - an instance of a %60bunyan%60 logger to use internally.%0A *                             this is meant to be used by the %60child%60 method.
 %0A */
@@ -722,16 +722,24 @@
 fig = %7B%7D
+, logger
 ) %7B%0A  co
@@ -799,21 +799,24 @@
 ;%0A  
-const
+logger =
  logger 
 = bu
@@ -811,17 +811,18 @@
  logger 
-=
+%7C%7C
  bunyan.
@@ -872,69 +872,14 @@
 %0A%0A  
-// Attach a few extras to instances of ClientLogger%0A  logger.
+this._
 conf
@@ -895,153 +895,48 @@
 ig;%0A
-%0A
   
-return logger;%0A%7D%0A%0A// Extend child function to give _emit access to config in log children%0Aconst originalChild = bunyan.prototype.child;%0Abunyan
+this._logger = logger;%0A%7D%0A%0AClientLogger
 .pro
@@ -962,24 +962,10 @@
 tion
+ 
 (
-options, simple
 ) %7B%0A
@@ -990,95 +990,98 @@
 r = 
-originalChild.call(this, options, simple);%0A  childLogger.config = 
+this._logger.child.apply(this._logger, arguments);%0A  return new ClientLogger(
 this.
+_
 config
-;%0A  return
+,
  chi
@@ -1092,16 +1092,17 @@
 gger
+)
 ;%0A%7D%0A%0A// 
 Over
@@ -1101,337 +1101,193 @@
 %0A// 
-Overwrite logger functions to scrub out all fields, including pre stringified msg%0AforEach(BUNYAN_LOGGER_LEVELS, (type) =%3E %7B%0A  const original = bunyan.prototype%5Btype%5D;%0A  bunyan.prototype%5Btype%5D = function(...args) %7B%0A    const newArgs = args.map((arg) =%3E scrub(arg, this.config));%0A    return original.apply(this, newArgs);%0A  %7D
+Dynamically hoist + wrap bunyan log instance methods (logger.info, logger.warn, etc)%0ABUNYAN_LOGGER_LEVELS.forEach(level =%3E %7B%0A  ClientLogger.prototype%5Blevel%5D = logForLevel(level);
 %0A%7D);%0A%0A
+%0A
 /**%0A

Update client entry for parity