'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.createExtensionLogger = exports.baseFileTransportOpts = undefined;

var _regenerator;

function _load_regenerator() {
  return _regenerator = _interopRequireDefault(require('babel-runtime/regenerator'));
}

var _winston;

function _load_winston() {
  return _winston = _interopRequireDefault(require('winston'));
}

var _path;

function _load_path() {
  return _path = _interopRequireDefault(require('path'));
}

var _constants;

function _load_constants() {
  return _constants = require('../constants');
}

var _analytics;

function _load_analytics() {
  return _analytics = require('../analytics/analytics');
}

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }

// Store the extensionsLoggers to prevent create more than one logger for the same extension
// in case the extension developer use api.logger more than once
var extensionsLoggers = new Map();

var baseFileTransportOpts = exports.baseFileTransportOpts = {
  filename: (_path || _load_path()).default.join((_constants || _load_constants()).GLOBAL_LOGS, 'debug.log'),
  json: false,
  // Make it debug level also in production until the product will be more stable. in the future this should be changed to error
  level: process.env.NODE_ENV === 'production' ? 'debug' : 'debug',
  maxsize: 10 * 1024 * 1024, // 10MB
  maxFiles: 10,
  colorize: true,
  prettyPrint: true,
  // If true, log files will be rolled based on maxsize and maxfiles, but in ascending order.
  // The filename will always have the most recent log lines. The larger the appended number, the older the log file
  tailable: true
};

var exceptionsFileTransportOpts = Object.assign({}, baseFileTransportOpts, {
  filename: (_path || _load_path()).default.join((_constants || _load_constants()).GLOBAL_LOGS, 'exceptions.log')
});

var logger = new (_winston || _load_winston()).default.Logger({
  transports: [new (_winston || _load_winston()).default.transports.File(baseFileTransportOpts)],
  exceptionHandlers: [new (_winston || _load_winston()).default.transports.File(exceptionsFileTransportOpts)],
  exitOnError: false
});

/**
 * Create a logger instance for extension
 * The extension name will be added as label so it will appear in the begining of each log line
 * The logger is cached for each extension so there is no problem to use getLogger few times for the same extension
 * @param {string} extensionName
 */
var createExtensionLogger = exports.createExtensionLogger = function createExtensionLogger(extensionName) {
  // Getting logger from cache
  var existingLogger = extensionsLoggers.get(extensionName);

  if (existingLogger) {
    return existingLogger;
  }
  var extensionFileTransportOpts = Object.assign({}, baseFileTransportOpts, {
    filename: (_path || _load_path()).default.join((_constants || _load_constants()).GLOBAL_LOGS, 'extensions.log'),
    label: extensionName
  });
  var extLogger = new (_winston || _load_winston()).default.Logger({
    transports: [new (_winston || _load_winston()).default.transports.File(extensionFileTransportOpts)],
    exceptionHandlers: [new (_winston || _load_winston()).default.transports.File(extensionFileTransportOpts)],
    exitOnError: false
  });
  extensionsLoggers.set(extensionName, extLogger);
  return extLogger;
};

// @credit Kegsay from https://github.com/winstonjs/winston/issues/228
// it solves an issue when exiting the code explicitly and the log file is not written
logger.exitAfterFlush = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee() {
  var code = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
  var commandName = arguments[1];
  var level, msg;
  return (_regenerator || _load_regenerator()).default.wrap(function _callee$(_context) {
    while (1) {
      switch (_context.prev = _context.next) {
        case 0:
          _context.next = 2;
          return (_analytics || _load_analytics()).Analytics.sendData();

        case 2:
          level = void 0;
          msg = void 0;

          if (code === 0) {
            level = 'info';
            msg = `[*] the command ${commandName} has been completed successfully`;
          } else {
            level = 'error';
            msg = `[*] the command ${commandName} has been terminated with an error code ${code}`;
          }
          logger.log(level, msg, function () {
            var numFlushes = 0;
            var numFlushed = 0;
            Object.keys(logger.transports).forEach(function (k) {
              if (logger.transports[k]._stream) {
                numFlushes += 1;
                logger.transports[k]._stream.once('finish', function () {
                  numFlushed += 1;
                  if (numFlushes === numFlushed) {
                    process.exit(code);
                  }
                });
                logger.transports[k]._stream.end();
              }
            });
            if (numFlushes === 0) {
              process.exit(code);
            }
          });

        case 6:
        case 'end':
          return _context.stop();
      }
    }
  }, _callee, undefined);
}));

if (process.env.BIT_LOG) {
  var level = process.env.BIT_LOG;
  logger.add((_winston || _load_winston()).default.transports.Console, { level });
  logger.cli();
}

exports.default = logger;