import _extends from "@babel/runtime/helpers/extends";

/**
 ***********************************************************************************************************************
 *
 *                                     单位转换的公共方法
 *
 ********************************************************************************************************************** */
import moment from 'moment';
import { toDecimal } from "./toDecimal";
import { Units } from "./constantUnits";
/**
 * @typedef {'ms'|'s'|'b'|'kb'|'mb'|'gb'|'tb'|'bps'|'kbps'|'mbps'|'gbps'|'tbps'|'人'|'个'|'万人'|'万个'|'次'|'万次'|'ts'|'%'|'num'|'B'| 'KB'| 'MB'| 'GB'| 'TB'|'Bps'| 'KBps'| 'MBps'| 'GBps'| 'TBps'} unit
 */

/**
 * 单位进制换算公共方法
 * @class UnitFormat
 * @classdesc 单位进制工具类
 * @param {number} value 数值
 * @param {unit} unit 单位
 * @param {object} config 配置
 */

export var UnitFormat = function UnitFormat(value, unit, config) {
  return new _UnitFormat(value, unit, config);
};
/**
 * UnitFormat默认配置项
 * decimal：2 保留小数两位
 * isMinUintFloor：true 是否最小单位向下取整
 * @constant formatConfig
 */

var formatConfig = {
  decimal: 2,
  isMinUintFloor: false,
  customCarry: NaN
}; // 错误信息

var errorMessage = {
  default: {
    key: 'defalut',
    message: '参数错误'
  },
  unitError: {
    key: 'unitError',
    message: '单位不符合要求，请检查'
  },
  valueIsNaN: {
    key: 'valueIsNaN',
    message: '参数值value非数字，请检查'
  },
  valueIsNegative: {
    key: 'valueIsNegative',
    message: '参数值value为负数，请检查'
  },
  timestampError: {
    key: 'timestampError',
    message: '参数不符合时间戳格式，请将头函数第一个参数设置为number类型，第二个参数设置为ts'
  },
  convertError: {
    key: 'convertError',
    message: '转换类型不匹配，无法转换'
  }
}; // 判断是否是Byte系统单位
// 此系统单位保持大小写区分

var isBType = function isBType(u) {
  if (Units.B_units.keys.indexOf(u) != -1 || Units.Bps_units.keys.indexOf(u) != -1) {
    return true;
  }

  return false;
};
/**
 * 内置处理类
 * @private
 */


var _UnitFormat = function _UnitFormat(value, _unit2) {
  var _this = this;

  var _config2 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : formatConfig;

  this.formatTimestamp = function (formatStr) {
    if (_this.unit != Units.ts.key) {
      return _this.setError(errorMessage.timestampError.key, _this.unit);
    }

    if (_this.error) {
      return _this.setError(null, null, false);
    }

    _this.result.unit = Units.ts.key;
    _this.result.value = moment(_this.value).format(formatStr);
    return _this.result;
  };

  this.unitToUnit = function (newUnit) {
    var _newUnit = isBType(newUnit) ? newUnit : newUnit.toLowerCase(); // 单位转换成小写


    if (!_this.checkUnitType(_newUnit)) {
      return _this.setError(errorMessage.unitError.key, _newUnit);
    }

    if (_this.error) {
      return _this.setError(null, null, false);
    }

    if (Units[_this.unit].type != Units[_newUnit].type) {
      // 判断源，目的单位是否同组
      _this.setError(errorMessage.convertError.key, _this.unit + "->" + _newUnit);
    } else {
      // 通过源，目的单位的进制，计算结果
      if (_this.result.value < 0) {
        return _this.setError(errorMessage.valueIsNegative.key, _this.result.value);
      }

      var new_group = Units[Units[_newUnit].type]; // 当前单位组

      var new_carry = isNaN(_this.config.customCarry) ? new_group.carry : _this.config.customCarry;
      _this.result.value = _this.result.value * Math.pow(new_carry, Units[_this.unit].carryIndex - Units[_newUnit].carryIndex);
      _this.result.unit = Units[_newUnit].name; // 规范返回单位
      // 若目的单位是单位组中基础单位，则保留整数（%分号转数字除外），否则保留两位小数

      if (_newUnit === new_group.keys[0] && Units[_newUnit].type != 'bps_units') {
        if (Units[_newUnit].type != 'percent_units') {
          if (_this.config.isMinUintFloor) {
            _this.result.value = Math.floor(_this.result.value);
          } else {
            _this.result.value = toDecimal(_this.result.value, _this.config.decimal);
          }
        }
      } else {
        _this.result.value = toDecimal(_this.result.value, _this.config.decimal);
      }
    }

    return _this.result;
  };

  this.fitUnit = function () {
    if (_this.error) {
      return _this.setError(null, null, false);
    }

    try {
      // 时间戳转换（非进制转换）
      if (_this.unit === Units.ts.key) {
        _this.result.unit = Units.ts.key;
        _this.result.value = moment(_this.value).format(Units.dateFormat_default);
        return _this.result;
      } // 百分号 数字只做保留两位小数处理处理（非进制转换）


      if (_this.unit === Units['%'].name || _this.unit === Units.num.name) {
        _this.result.unit = _this.unit;
        _this.result.value = toDecimal(_this.value, _this.config.decimal);
        return _this.result;
      } // 流量，流速，秒毫秒，万进制单位转换（进制转换）


      var num = _this.value;
      var old_group = Units[Units[_this.unit].type]; // 当前单位类型组

      var old_carry = isNaN(_this.config.customCarry) ? old_group.carry : _this.config.customCarry;
      num *= Math.pow(old_carry, Units[_this.unit].carryIndex); // 将单位值转换成该类型单位最小单位

      if (num < 0) {
        return _this.setError(errorMessage.valueIsNegative.key, num);
      }

      var carryIndex = num < 1 ? 0 : Math.floor(Math.log(num) / Math.log(old_carry)); // 计算出数值对于该单位进制指数
      // 对于超出单位组最大单位的指数，记为最大单位指数，不向后进位

      if (carryIndex >= old_group.keys.length) {
        carryIndex = old_group.keys.length - 1;
      }

      var target_unit = old_group.keys[carryIndex]; // 目标单位

      num /= Math.pow(old_carry, Units[target_unit].carryIndex); // 单位值向目标单位转换
      // 最小单位保留整数，其他保留两位小数

      if (carryIndex === 0 && Units[_this.unit].type != 'bps_units' && _this.config.isMinUintFloor) {
        num = Math.floor(num);
      } else {
        num = toDecimal(num, _this.config.decimal);
      }

      _this.result.unit = Units[target_unit].name; // 单位规范

      _this.result.value = num;
      return _this.result;
    } catch (e) {
      return _this.setError(e);
    }
  };

  this.checkConfig = function (config) {
    var _config = formatConfig; // 默认配置和参数配置组装

    if (config) {
      _config = _extends({}, _config, config);
    } // 保留小数位校验


    if (isNaN(_config.decimal)) {
      _config.decimal = formatConfig.decimal;
    } else if (_config.decimal < 0) {
      _config.decimal = formatConfig.decimal;
    }

    return _config;
  };

  this.checkUnitType = function (unit) {
    var hasUnit = false;

    for (var key in Units) {
      if (Units.hasOwnProperty(key)) {
        var element = Units[key];

        if (element.hasOwnProperty('key')) {
          var _unit = element.key;

          if (_unit === unit) {
            hasUnit = true;
          }
        }
      }
    }

    return hasUnit;
  };

  this.setError = function (errorKey) {
    var info = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
    var isLog = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
    var message = '';

    if (errorKey) {
      if (errorKey.message) {
        message = "tryCatchLog:" + errorKey.message;
      } else {
        message = errorKey;

        if (errorMessage[errorKey]) {
          _this.errorKey = errorKey;
          message = errorMessage[_this.errorKey].message;
        }

        message += "(" + info + ")";
      }
    }

    if (isLog) {
      console.log(message);
    } // 设置返回值为默认空值


    _this.result.value = Units.empty;
    _this.result.unit = Units.empty;
    _this.error = true; // 设置错误标记位为true

    return _this.result;
  };

  try {
    // 初始化返回值
    this.result = {
      old: {
        value: value,
        unit: _unit2
      },
      value: value,
      unit: _unit2
    };
    this.config = this.checkConfig(_config2);
    this.value = Number.parseFloat(value); // 单位值不存在的情况设置错误信息

    if (_unit2) {
      this.unit = isBType(_unit2) ? _unit2 : _unit2.toLowerCase();
    } else {
      this.setError(errorMessage.unitError.key, _unit2, false);
      return;
    }

    this.error = false; // 初始化错误标记位

    this.errorKey = errorMessage.default.key; // 初始化错误信息key

    this.result.value = this.value;
    this.result.unit = _unit2;

    if (isNaN(this.value)) {
      this.setError(errorMessage.valueIsNaN.key, this.value, false);
    }

    if (!this.checkUnitType(this.unit)) {
      this.setError(errorMessage.unitError.key, this.unit, false);
    }
  } catch (e) {
    this.setError(e);
  }
}
/**
 * 格式化日期字符串
 * @memberof UnitFormat#
 * @function formatTimestamp
 * @param {string} formatStr 格式化日期字符串 例：YYYY-MM-DD HH:mm:ss
 * @returns {string}
 */
;