'use strict';

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _serializeError;

function _load_serializeError() {
  return _serializeError = _interopRequireDefault(require('serialize-error'));
}

var _path;

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

var _objectHash;

function _load_objectHash() {
  return _objectHash = _interopRequireDefault(require('object-hash'));
}

var _uniqid;

function _load_uniqid() {
  return _uniqid = _interopRequireDefault(require('uniqid'));
}

var _yn;

function _load_yn() {
  return _yn = _interopRequireDefault(require('yn'));
}

var _ramda;

function _load_ramda() {
  return _ramda = _interopRequireDefault(require('ramda'));
}

var _os;

function _load_os() {
  return _os = _interopRequireDefault(require('os'));
}

var _child_process;

function _load_child_process() {
  return _child_process = require('child_process');
}

var _globalConfig;

function _load_globalConfig() {
  return _globalConfig = require('../api/consumer/lib/global-config');
}

var _prompts;

function _load_prompts() {
  return _prompts = require('../prompts');
}

var _constants;

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

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

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var LEVEL = {
  DEBUG: 'debug',
  INFO: 'info',
  WARNING: 'warning',
  ERROR: 'error',
  FATAL: 'fatal'
};

var Breadcrumb = function Breadcrumb(category, message, data) {
  _classCallCheck(this, Breadcrumb);

  this.category = category;
  this.message = message;
  this.data = data;
};

var Analytics = function () {
  function Analytics() {
    _classCallCheck(this, Analytics);
  }

  _createClass(Analytics, null, [{
    key: 'getID',
    value: function getID() {
      var id = (0, (_globalConfig || _load_globalConfig()).getSync)((_constants || _load_constants()).CFG_ANALYTICS_USERID_KEY);
      if (id) return id;
      var newId = (0, (_uniqid || _load_uniqid()).default)();
      (0, (_globalConfig || _load_globalConfig()).setSync)((_constants || _load_constants()).CFG_ANALYTICS_USERID_KEY, newId);
      return newId;
    }
  }, {
    key: 'promptAnalyticsIfNeeded',
    value: function promptAnalyticsIfNeeded(cmd) {
      function shouldPromptForAnalytics() {
        // do not prompt analytics approval for bit config command (so you can configure it in CI envs)
        if (cmd.length && cmd[0] !== 'config') {
          var analyticsReporting = (0, (_globalConfig || _load_globalConfig()).getSync)((_constants || _load_constants()).CFG_ANALYTICS_REPORTING_KEY);
          var errorReporting = (0, (_globalConfig || _load_globalConfig()).getSync)((_constants || _load_constants()).CFG_ANALYTICS_ERROR_REPORTS_KEY);
          return (_ramda || _load_ramda()).default.isNil(analyticsReporting) && (_ramda || _load_ramda()).default.isNil(errorReporting);
        }
        return false;
      }

      if (shouldPromptForAnalytics()) {
        var uniqId = (0, (_uniqid || _load_uniqid()).default)();
        if (!(0, (_globalConfig || _load_globalConfig()).getSync)((_constants || _load_constants()).CFG_ANALYTICS_USERID_KEY)) (0, (_globalConfig || _load_globalConfig()).setSync)((_constants || _load_constants()).CFG_ANALYTICS_USERID_KEY, uniqId);
        return (0, (_prompts || _load_prompts()).analyticsPrompt)().then(function (_ref) {
          var analyticsResponse = _ref.analyticsResponse;

          (0, (_globalConfig || _load_globalConfig()).setSync)((_constants || _load_constants()).CFG_ANALYTICS_REPORTING_KEY, (0, (_yn || _load_yn()).default)(analyticsResponse));
          if (!(0, (_yn || _load_yn()).default)(analyticsResponse)) {
            return (0, (_prompts || _load_prompts()).errorReportingPrompt)().then(function (_ref2) {
              var errResponse = _ref2.errResponse;

              return (0, (_globalConfig || _load_globalConfig()).setSync)((_constants || _load_constants()).CFG_ANALYTICS_ERROR_REPORTS_KEY, (0, (_yn || _load_yn()).default)(errResponse));
            });
          }
          return Promise.resolve();
        });
      }
      return Promise.resolve();
    }
  }, {
    key: '_maskString',
    value: function _maskString(str) {
      return str.replace(/[A-Za-z]/g, 'x');
    }
  }, {
    key: '_hashLightly',
    value: function _hashLightly(value) {
      var _this = this;

      switch (typeof value) {
        case 'undefined':
        case 'number':
        case 'boolean':
          return value;
        case 'string':
          return this._maskString(value);
        case 'object':
          if (Array.isArray(value)) return value.map(function (item) {
            return _this._hashLightly(item);
          });
          if (value === null) return value;
          return (0, (_objectHash || _load_objectHash()).default)(value);
        default:
          return (0, (_objectHash || _load_objectHash()).default)(value);
      }
    }
  }, {
    key: '_hashFlags',
    value: function _hashFlags(flags) {
      var _this2 = this;

      var hashedFlags = {};
      var definedFlags = (_ramda || _load_ramda()).default.filter(function (flag) {
        return typeof flag !== 'undefined';
      }, flags);
      if (this.anonymous && !(_ramda || _load_ramda()).default.isEmpty(definedFlags)) {
        Object.keys(definedFlags).forEach(function (key) {
          hashedFlags[key] = _this2._hashLightly(flags[key]);
        });
        return hashedFlags;
      }
      return definedFlags;
    }
  }, {
    key: '_hashArgs',
    value: function _hashArgs(args) {
      var _this3 = this;

      if (!this.anonymous) return args;
      return args.map(function (arg) {
        return _this3._hashLightly(arg);
      });
    }
  }, {
    key: 'init',
    value: function init(command, flags, args, version) {
      this.anonymous = (0, (_yn || _load_yn()).default)((0, (_globalConfig || _load_globalConfig()).getSync)((_constants || _load_constants()).CFG_ANALYTICS_ANONYMOUS_KEY), { default: true });
      this.command = command;
      this.flags = this._hashFlags(flags);
      this.release = version;
      this.args = this._hashArgs(args);
      this.nodeVersion = process.version;
      this.os = process.platform;
      this.level = LEVEL.INFO;
      this.username = !this.anonymous ? (0, (_globalConfig || _load_globalConfig()).getSync)((_constants || _load_constants()).CFG_USER_EMAIL_KEY) || (0, (_globalConfig || _load_globalConfig()).getSync)((_constants || _load_constants()).CFG_USER_NAME_KEY) || (_os || _load_os()).default.hostname() || this.getID() : this.getID();
      this.analytics_usage = (0, (_yn || _load_yn()).default)((0, (_globalConfig || _load_globalConfig()).getSync)((_constants || _load_constants()).CFG_ANALYTICS_REPORTING_KEY), { default: false });
      this.error_usage = this.analytics_usage ? true : (0, (_yn || _load_yn()).default)((0, (_globalConfig || _load_globalConfig()).getSync)((_constants || _load_constants()).CFG_ANALYTICS_ERROR_REPORTS_KEY), { default: false });
      this.environment = (0, (_globalConfig || _load_globalConfig()).getSync)((_constants || _load_constants()).CFG_ANALYTICS_ENVIRONMENT_KEY) || (_constants || _load_constants()).DEFAULT_BIT_ENV;
    }
  }, {
    key: 'sendData',
    value: function sendData() {
      var _this4 = this;

      return new Promise(function (resolve, reject) {
        if (_this4.analytics_usage || _this4.error_usage && !_this4.success) {
          var file = (_path || _load_path()).default.join(__dirname, 'analytics-sender.js');
          var forked = (0, (_child_process || _load_child_process()).fork)(file, { silent: true }); // switch to `false` to debug the child
          // console.log('sending', this.toObject()); // un-comment to see the data sent to Analytics
          forked.send(_this4.toObject());
          forked.on('message', function () {
            // makes sure the data has been sent to the child.
            // without it, when the message is large, it exits before the child got the complete message
            resolve();
          });
          forked.on('error', function (err) {
            reject(err);
          });
        } else {
          resolve();
        }
      });
    }
  }, {
    key: 'setError',
    value: function setError() {
      var level = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : LEVEL.ERROR;
      var err = arguments[1];

      this.level = level;
      this.error = (0, (_serializeError || _load_serializeError()).default)(err);
      this.success = false;
    }

    /**
     * eventually goes to the "ADDITIONAL DATA" section in Sentry
     */

  }, {
    key: 'setExtraData',
    value: function setExtraData(key, value) {
      this.extra[key] = value;
    }
  }, {
    key: 'incExtraDataKey',
    value: function incExtraDataKey(key, value) {
      if (this.extra[key]) {
        this.extra[key] += value || 1;
      } else {
        this.extra[key] = value || 1;
      }
    }
  }, {
    key: 'hashData',
    value: function hashData(data) {
      if (this.anonymous) {
        return (0, (_objectHash || _load_objectHash()).default)(data);
      }
      return data;
    }
  }, {
    key: 'addBreadCrumb',
    value: function addBreadCrumb(category, message, data) {
      this.breadcrumbs.push(new Breadcrumb(category, message, data));
    }
  }, {
    key: 'toObject',
    value: function toObject() {
      return {
        username: this.username,
        command: this.command,
        flags: this.flags,
        args: this.args,
        release: this.release,
        extra: this.extra,
        nodeVersion: this.nodeVersion,
        os: this.os,
        level: this.level,
        error: this.error,
        success: this.success,
        breadcrumbs: this.breadcrumbs,
        analytics_usage: this.analytics_usage,
        error_usage: this.analytics_usage,
        environment: this.environment
      };
    }
  }]);

  return Analytics;
}();

Analytics.flags = {};
Analytics.success = true;
Analytics.extra = {};
Analytics.breadcrumbs = [];


module.exports = { LEVEL, Analytics };