'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }

var i18next = _interopDefault(require('i18next'));
var ICU = require('@ies/intl-icu-plugin');
var ICU__default = _interopDefault(ICU);
var InContext = _interopDefault(require('@ies/intl-incontext-plugin'));

function _classCallCheck(instance, Constructor) {
  if (!(instance instanceof Constructor)) {
    throw new TypeError("Cannot call a class as a 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);
  }
}

function _createClass(Constructor, protoProps, staticProps) {
  if (protoProps) _defineProperties(Constructor.prototype, protoProps);
  if (staticProps) _defineProperties(Constructor, staticProps);
  Object.defineProperty(Constructor, "prototype", {
    writable: false
  });
  return Constructor;
}

function _toConsumableArray(arr) {
  return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
}

function _arrayWithoutHoles(arr) {
  if (Array.isArray(arr)) return _arrayLikeToArray(arr);
}

function _iterableToArray(iter) {
  if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
}

function _unsupportedIterableToArray(o, minLen) {
  if (!o) return;
  if (typeof o === "string") return _arrayLikeToArray(o, minLen);
  var n = Object.prototype.toString.call(o).slice(8, -1);
  if (n === "Object" && o.constructor) n = o.constructor.name;
  if (n === "Map" || n === "Set") return Array.from(o);
  if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
}

function _arrayLikeToArray(arr, len) {
  if (len == null || len > arr.length) len = arr.length;

  for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];

  return arr2;
}

function _nonIterableSpread() {
  throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}

function _createForOfIteratorHelper(o, allowArrayLike) {
  var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];

  if (!it) {
    if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
      if (it) o = it;
      var i = 0;

      var F = function () {};

      return {
        s: F,
        n: function () {
          if (i >= o.length) return {
            done: true
          };
          return {
            done: false,
            value: o[i++]
          };
        },
        e: function (e) {
          throw e;
        },
        f: F
      };
    }

    throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
  }

  var normalCompletion = true,
      didErr = false,
      err;
  return {
    s: function () {
      it = it.call(o);
    },
    n: function () {
      var step = it.next();
      normalCompletion = step.done;
      return step;
    },
    e: function (e) {
      didErr = true;
      err = e;
    },
    f: function () {
      try {
        if (!normalCompletion && it.return != null) it.return();
      } finally {
        if (didErr) throw err;
      }
    }
  };
}

/**
 * Currency code list
 * https://www.currency-iso.org/en/home/tables/table-a1.html
 */
var currency = ['AFN', 'EUR', 'ALL', 'DZD', 'USD', 'AOA', 'XCD', 'ARS', 'AMD', 'AWG', 'AUD', 'AZN', 'BSD', 'BHD', 'BDT', 'BBD', 'BYN', 'BZD', 'XOF', 'BMD', 'INR', 'BTN', 'BOB', 'BOV', 'BAM', 'BWP', 'NOK', 'BRL', 'BND', 'BGN', 'BIF', 'CVE', 'KHR', 'XAF', 'CAD', 'KYD', 'CLP', 'CLF', 'CNY', 'COP', 'COU', 'KMF', 'CDF', 'NZD', 'CRC', 'HRK', 'CUP', 'CUC', 'ANG', 'CZK', 'DKK', 'DJF', 'DOP', 'EGP', 'SVC', 'ERN', 'ETB', 'FKP', 'FJD', 'XPF', 'GMD', 'GEL', 'GHS', 'GIP', 'GTQ', 'GBP', 'GNF', 'GYD', 'HTG', 'HNL', 'HKD', 'HUF', 'ISK', 'IDR', 'XDR', 'IRR', 'IQD', 'ILS', 'JMD', 'JPY', 'JOD', 'KZT', 'KES', 'KPW', 'KRW', 'KWD', 'KGS', 'LAK', 'LBP', 'LSL', 'ZAR', 'LRD', 'LYD', 'CHF', 'MOP', 'MKD', 'MGA', 'MWK', 'MYR', 'MVR', 'MRO', 'MUR', 'XUA', 'MXN', 'MXV', 'MDL', 'MNT', 'MAD', 'MZN', 'MMK', 'NAD', 'NPR', 'NIO', 'NGN', 'OMR', 'PKR', 'PAB', 'PGK', 'PYG', 'PEN', 'PHP', 'PLN', 'QAR', 'RON', 'RUB', 'RWF', 'SHP', 'WST', 'STD', 'SAR', 'RSD', 'SCR', 'SLL', 'SGD', 'XSU', 'SBD', 'SOS', 'SSP', 'LKR', 'SDG', 'SRD', 'SZL', 'SEK', 'CHE', 'CHW', 'SYP', 'TWD', 'TJS', 'TZS', 'THB', 'TOP', 'TTD', 'TND', 'TRY', 'TMT', 'UGX', 'UAH', 'AED', 'USN', 'UYU', 'UYI', 'UZS', 'VUV', 'VEF', 'VND', 'YER', 'ZMW', 'ZWL', 'XBA', 'XBB', 'XBC', 'XBD', 'XTS', 'XXX', 'XAU', 'XPD', 'XPT', 'XAG'];
var numberFormat = {};

for (var i = 0; i < currency.length; i++) {
  numberFormat[currency[i]] = {
    style: 'currency',
    currency: currency[i]
  };
}

var defaultFormats = {
  number: numberFormat
};

var types = {
  LOGGER: 'logger',
  LAMGUAGE_DETECTOR: 'languageDetector',
  LAMGUAGE_TRANSFORMER: 'languageTransformer',
  BACKEND: 'backend'
};
function isTypes(type) {
  return function (itm) {
    return itm.type === type;
  };
}

function formatLang(lng, plugins) {
  var formatLang = lng;
  (plugins || []).map(function (plugin) {
    formatLang = plugin.process(lng) || formatLang;
  });
  return formatLang;
}

var defaultFallbackLanguage = 'zh-CN';
var defaultConfig = {
  lng: defaultFallbackLanguage,
  fallbackLng: ['en-US'],
  inContext: true
};
var defaultPlugins = [ICU__default, InContext];
/**
 * I18n内核
 * 安全校验
 */

var I18next = /*#__PURE__*/function () {
  function I18next(config, plugins) {
    var _this = this;

    _classCallCheck(this, I18next);

    this._waitingToAddResourceBundle = [];

    this.t = function (keys, options, fallbackText) {
      var separatorMock = Array.isArray(keys) ? Array.from(keys).map(function () {
        return ' ';
      }).join('') : Array(keys.length).fill(' '); // fixed: 去除默认lngs，有lngs i18next就会忽略lng

      var opt = Object.assign({
        keySeparator: separatorMock,
        nsSeparator: separatorMock
      }, options);

      if ('thirdParamFallback' in _this.config && _this.config.thirdParamFallback) {
        opt.thirdParamFallback = true;
      }

      return _this.instance.t(keys, fallbackText, opt);
    };

    this._handlePlugins(plugins);

    this._handleConfigs(config);

    this.instance = i18next.createInstance();
    this.instance.isInitialized = false;
  }

  _createClass(I18next, [{
    key: "_handlePlugins",
    value: function _handlePlugins(plugins) {
      this.plugins = Array.isArray(plugins) ? plugins.concat(defaultPlugins) : defaultPlugins;
    }
  }, {
    key: "_handleConfigs",
    value: function _handleConfigs(config) {
      this.userLng = (config === null || config === void 0 ? void 0 : config.lng) || null; // 用户自己设定的 lng

      this.config = Object.assign({}, defaultConfig, config || {});
    }
  }, {
    key: "language",
    get: function get() {
      return (this.instance || {}).language;
    }
  }, {
    key: "createInstance",
    value: function createInstance() {
      var _this2 = this;

      return new Promise(function (resolve, reject) {
        // fixed: 非浏览器环境不支持incontext
        // fixed: Cocos 有 window 但不使用 in-context
        // feat: 支持手动关闭inContext
        if (typeof window !== 'undefined' && !window.CocosEngine && _this2.config.inContext) {
          _this2.config.postProcess = [].concat(['inContext'], _this2.config.postProcess || []);
        }

        _this2.plugins.map(function (p) {
          if (p.name === 'IES_INTL_ICU_PLUGIN') {
            p.staticInit(_this2.instance);
          }

          _this2.instance.use(p);
        });

        var config = _this2.config;
        _this2.config.formats = Object.assign({}, _this2.config.formats, defaultFormats);
        var formatLng = formatLang(config.lng, _this2.plugins.filter(isTypes(types.LAMGUAGE_TRANSFORMER)));

        _this2.instance.init(Object.assign({}, config, {
          lng: formatLng,
          i18nFormat: {
            formats: _this2.config.formats
          }
        }), function (err, t) {
          // 初始化好了
          try {
            // 把等待添加的东西都加进去
            var _iterator = _createForOfIteratorHelper(_this2._waitingToAddResourceBundle),
                _step;

            try {
              for (_iterator.s(); !(_step = _iterator.n()).done;) {
                var _this2$instance;

                var item = _step.value;

                (_this2$instance = _this2.instance).addResourceBundle.apply(_this2$instance, _toConsumableArray(item));
              }
            } catch (err) {
              _iterator.e(err);
            } finally {
              _iterator.f();
            }

            _this2._waitingToAddResourceBundle = []; // eslint-disable-next-line no-empty
          } catch (err) {}

          if (!err) {
            _this2._updateLanguages();

            resolve({
              t: t,
              err: err
            });
          }

          _this2.init = true;
          reject({
            t: t,
            err: err
          });
        });
      });
    }
  }, {
    key: "_updateLanguages",
    value: function _updateLanguages() {
      this.languages = this.instance ? Array.from(new Set([this.instance.language].concat(_toConsumableArray(this.instance.languages)))) : null;
    }
  }, {
    key: "getLanguages",
    value: function getLanguages() {
      return this.languages;
    }
  }, {
    key: "changeLanguage",
    value: function changeLanguage(lng, callback) {
      var _this3 = this;

      this.config.lng = lng;
      this.instance.changeLanguage(lng, function (err, t) {
        if (!err) {
          _this3._updateLanguages();
        }

        callback && callback(err, t);
      });
    }
  }, {
    key: "changeLanguageWithPromise",
    value: function changeLanguageWithPromise(lng) {
      var _this4 = this;

      return new Promise(function (resolve, reject) {
        _this4.config.lng = lng;

        _this4.instance.changeLanguage(lng, function (err, t) {
          if (err) {
            reject({
              err: err,
              t: t
            });
          }

          _this4._updateLanguages();

          resolve({
            err: err,
            t: t
          });
        });
      });
    }
  }, {
    key: "getDir",
    value: function getDir(lng) {
      return this.instance.dir(lng);
    }
  }, {
    key: "addResourceBundle",
    value: function addResourceBundle(lng, ns, resources, deep, overwrite) {
      if (this.instance.isInitialized) {
        return this.instance.addResourceBundle(lng, ns, resources, deep, overwrite);
      } // 还没初始化好


      this._waitingToAddResourceBundle.push([lng, ns, resources, !!deep, !!overwrite]);

      return this.instance;
    }
  }]);

  return I18next;
}();

var PREFIX = 'Starling_intl:';
var logger = {
  warn: function warn() {
    var _console;

    var prefix = "".concat(PREFIX, " [WARNING]");

    for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
      args[_key] = arguments[_key];
    }

    (_console = console).warn.apply(_console, [prefix].concat(args));
  },
  error: function error() {
    var _console2;

    var prefix = "".concat(PREFIX, " [ERROR]");

    for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
      args[_key2] = arguments[_key2];
    }

    (_console2 = console).error.apply(_console2, [prefix].concat(args));
  }
};

function promiseQueue(executors) {
  return new Promise(function (resolve, reject) {
    if (!Array.isArray(executors)) {
      executors = Array.from(executors);
    }

    if (executors.length <= 0) {
      return resolve([]);
    }

    var res = [];
    executors = executors.map(function (x, i) {
      return function () {
        var p = typeof x === 'function' ? new Promise(x) : Promise.resolve(x);
        p.then(function (response) {
          res[i] = response;

          if (i === executors.length - 1) {
            resolve(res);
          } else {
            executors[i + 1]();
          }
        }, reject);
      };
    });
    executors[0]();
  });
}

function _await(value, then, direct) {
  if (direct) {
    return then ? then(value) : value;
  }

  if (!value || !value.then) {
    value = Promise.resolve(value);
  }

  return then ? value.then(then) : value;
}

function _catch(body, recover) {
  try {
    var result = body();
  } catch (e) {
    return recover(e);
  }

  if (result && result.then) {
    return result.then(void 0, recover);
  }

  return result;
}

function _empty() {}

function _awaitIgnored(value, direct) {
  if (!direct) {
    return value && value.then ? value.then(_empty) : Promise.resolve();
  }
}

function _async(f) {
  return function () {
    for (var args = [], i = 0; i < arguments.length; i++) {
      args[i] = arguments[i];
    }

    try {
      return Promise.resolve(f.apply(this, args));
    } catch (e) {
      return Promise.reject(e);
    }
  };
}

var IntlModuleType;

(function (IntlModuleType) {
  IntlModuleType["intl3rdParty"] = "intl3rdParty";
  IntlModuleType["backend"] = "backend";
  IntlModuleType["logger"] = "logger";
  IntlModuleType["languageDetector"] = "languageDetector";
  IntlModuleType["postProcessor"] = "postProcessor";
  IntlModuleType["i18nFormat"] = "i18nFormat";
  IntlModuleType["3rdParty"] = "3rdParty";
})(IntlModuleType || (IntlModuleType = {}));
/**
 * I18n实例
 * 自定义配置
 */

var Intl = /*#__PURE__*/function () {
  function Intl() {
    var _this = this;

    _classCallCheck(this, Intl);

    this.t = function (keys, options, fallbackText) {
      if (!_this.ignoreWarning && (!_this.i18nInstance || !_this.i18nInstance.init)) {
        logger.error("The instance has not been initialized: i18n.t('".concat(keys, "'").concat(options ? ',' + JSON.stringify(options) : '', ");"));
        return fallbackText !== null && fallbackText !== void 0 ? fallbackText : Array.isArray(keys) ? keys[0] : keys;
      } // 有人给 key 传空字符串?


      if (!keys || typeof keys === 'string' && !keys.trim()) {
        return '';
      }

      return _this.i18nInstance.t(keys, options, fallbackText);
    };

    this.plugins = [];
    this.i18nInstance = new I18next();
  }

  _createClass(Intl, [{
    key: "use",
    value: function use(plugin) {
      if (!this.plugins.includes(plugin)) {
        this.plugins.push(plugin);
        return this;
      }

      logger.warn("Plugin: ".concat(plugin.name, " has beeninit installed."));
      return this;
    }
  }, {
    key: "init",
    value: function init(config, initCallback) {
      try {
        var _this3 = this;

        // ignore warning
        _this3.ignoreWarning = config.ignoreWarning;

        _this3.i18nInstance._handleConfigs(config);

        _this3.i18nInstance._handlePlugins(_this3.plugins);

        return _await(_catch(function () {
          return _await(_this3.i18nInstance.createInstance(), function (_ref) {
            var err = _ref.err,
                t = _ref.t;

            // 接入 Intl thirdParty 类型 Plugin
            var intlThirdPartyArray = _this3.plugins.filter(function (p) {
              return p.type === IntlModuleType.intl3rdParty;
            });

            return _await(promiseQueue(intlThirdPartyArray.map(_async(function (intlThirdParty) {
              if (!intlThirdParty || typeof intlThirdParty.init !== 'function') {
                return;
              }

              var initFunction = intlThirdParty.init instanceof Promise ? intlThirdParty.init : _async(function (context) {
                return Promise.resolve(intlThirdParty.init(context));
              });
              return _awaitIgnored(initFunction(_this3));
            }))), function () {
              typeof initCallback === 'function' && initCallback(err, t);
              return {
                err: err,
                t: t
              };
            });
          });
        }, function (err) {
          logger.error("The instance init error: ".concat(err));
          return {
            err: err,
            t: function t(key) {
              return key;
            }
          };
        }));
      } catch (e) {
        return Promise.reject(e);
      }
    }
  }, {
    key: "language",
    get: function get() {
      return (this.i18nInstance || {}).language;
    }
  }, {
    key: "setLang",
    value: function setLang(lng, callback) {
      var formatLng = formatLang(lng, this.plugins.filter(isTypes(types.LAMGUAGE_TRANSFORMER)));
      this.i18nInstance.changeLanguage(formatLng, callback);
    }
  }, {
    key: "getLanguages",
    value: function getLanguages() {
      return this.i18nInstance.getLanguages();
    }
  }, {
    key: "setLangWithPromise",
    value: function setLangWithPromise(lng) {
      var formatLng = formatLang(lng, this.plugins.filter(isTypes(types.LAMGUAGE_TRANSFORMER)));
      return this.i18nInstance.changeLanguageWithPromise(formatLng);
    }
  }, {
    key: "dir",
    value: function dir(lng) {
      return this.i18nInstance.getDir(lng);
    }
  }, {
    key: "addResourceBundle",
    value: function addResourceBundle(lng, ns, resources, deep, overwrite) {
      // to to something validate
      return this.i18nInstance.addResourceBundle(lng, ns, resources, deep, overwrite);
    }
  }]);

  return Intl;
}();

var I18n = new Intl();
var I18nConstructor = Intl;

Object.defineProperty(exports, 'IntlMessageFormat', {
  enumerable: true,
  get: function () {
    return ICU.IntlMessageFormat;
  }
});
exports.I18n = I18n;
exports.I18nConstructor = I18nConstructor;
exports.I18nCore = I18next;
exports.Intl = Intl;
exports.default = I18n;
