text: var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
  
  var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
  
  function _defaults(obj, defaults) { var keys = Object.getOwnPropertyNames(defaults); for (var i = 0; i < keys.length; i++) { var key = keys[i]; var value = Object.getOwnPropertyDescriptor(defaults, key); if (value && value.configurable && obj[key] === undefined) { Object.defineProperty(obj, key, value); } } return obj; }
  
  function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  
  function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  
  function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : _defaults(subClass, superClass); }
  
  import * as utils from './utils';
  import baseLogger from './logger';
  import EventEmitter from './EventEmitter';
  
  function remove(arr, what) {
    var found = arr.indexOf(what);
  
    while (found !== -1) {
      arr.splice(found, 1);
      found = arr.indexOf(what);
    }
  }
  
  var Connector = function (_EventEmitter) {
    _inherits(Connector, _EventEmitter);
  
    function Connector(backend, store, services) {
      var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
  
      _classCallCheck(this, Connector);
  
      var _this = _possibleConstructorReturn(this, _EventEmitter.call(this));
  
      _this.backend = backend;
      _this.store = store;
      _this.services = services;
      _this.options = options;
      _this.logger = baseLogger.create('backendConnector');
  
      _this.state = {};
      _this.queue = [];
  
      _this.backend && _this.backend.init && _this.backend.init(services, options.backend, options);
      return _this;
    }
  
    Connector.prototype.queueLoad = function queueLoad(languages, namespaces, callback) {
      var _this2 = this;
  
      // find what needs to be loaded
      var toLoad = [],
          pending = [],
          toLoadLanguages = [],
          toLoadNamespaces = [];
  
      languages.forEach(function (lng) {
        var hasAllNamespaces = true;
  
        namespaces.forEach(function (ns) {
          var name = lng + '|' + ns;
  
          if (_this2.store.hasResourceBundle(lng, ns)) {
            _this2.state[name] = 2; // loaded
          } else if (_this2.state[name] < 0) {
            // nothing to do for err
          } else if (_this2.state[name] === 1) {
            if (pending.indexOf(name) < 0) pending.push(name);
          } else {
            _this2.state[name] = 1; // pending
  
            hasAllNamespaces = false;
  
            if (pending.indexOf(name) < 0) pending.push(name);
            if (toLoad.indexOf(name) < 0) toLoad.push(name);
            if (toLoadNamespaces.indexOf(ns) < 0) toLoadNamespaces.push(ns);
          }
        });
  
        if (!hasAllNamespaces) toLoadLanguages.push(lng);
      });
  
      if (toLoad.length || pending.length) {
        this.queue.push({
          pending: pending,
          loaded: {},
          errors: [],
          callback: callback
        });
      }
  
      return {
        toLoad: toLoad,
        pending: pending,
        toLoadLanguages: toLoadLanguages,
        toLoadNamespaces: toLoadNamespaces
      };
    };
  
    Connector.prototype.loaded = function loaded(name, err, data) {
      var _this3 = this;
  
      var _name$split = name.split('|'),
          _name$split2 = _slicedToArray(_name$split, 2),
          lng = _name$split2[0],
          ns = _name$split2[1];
  
      if (err) this.emit('failedLoading', lng, ns, err);
  
      if (data) {
        this.store.addResourceBundle(lng, ns, data);
      }
  
      // set loaded
      this.state[name] = err ? -1 : 2;
      // callback if ready
      this.queue.forEach(function (q) {
        utils.pushPath(q.loaded, [lng], ns);
        remove(q.pending, name);
  
        if (err) q.errors.push(err);
  
        if (q.pending.length === 0 && !q.done) {
          q.errors.length ? q.callback(q.errors) : q.callback();
          _this3.emit('loaded', q.loaded);
          q.done = true;
        }
      });
  
      // remove done load requests
      this.queue = this.queue.filter(function (q) {
        return !q.done;
      });
    };
  
    Connector.prototype.read = function read(lng, ns, fcName, tried, wait, callback) {
      var _this4 = this;
  
      if (!tried) tried = 0;
      if (!wait) wait = 250;
  
      if (!lng.length) return callback(null, {}); // noting to load
  
      this.backend[fcName](lng, ns, function (err, data) {
        if (err && data /* = retryFlag */ && tried < 5) {
          setTimeout(function () {
            _this4.read.call(_this4, lng, ns, fcName, ++tried, wait * 2, callback);
          }, wait);
          return;
        }
        callback(err, data);
      });
    };
  
    Connector.prototype.load = function load(languages, namespaces, callback) {
      var _this5 = this;
  
      if (!this.backend) {
        this.logger.warn('No backend was added via i18next.use. Will not load resources.');
        return callback && callback();
      }
      var options = _extends({}, this.backend.options, this.options.backend);
  
      if (typeof languages === 'string') languages = this.services.languageUtils.toResolveHierarchy(languages);
      if (typeof namespaces === 'string') namespaces = [namespaces];
  
      var toLoad = this.queueLoad(languages, namespaces, callback);
      if (!toLoad.toLoad.length) {
        if (!toLoad.pending.length) callback(); // nothing to load and no pendings...callback now
        return; // pendings will trigger callback
      }
  
      // load with multi-load
      if (options.allowMultiLoading && this.backend.readMulti) {
        this.read(toLoad.toLoadLanguages, toLoad.toLoadNamespaces, 'readMulti', null, null, function (err, data) {
          if (err) _this5.logger.warn('loading namespaces ' + toLoad.toLoadNamespaces.join(', ') + ' for languages ' + toLoad.toLoadLanguages.join(', ') + ' via multiloading failed', err);
          if (!err && data) _this5.logger.log('loaded namespaces ' + toLoad.toLoadNamespaces.join(', ') + ' for languages ' + toLoad.toLoadLanguages.join(', ') + ' via multiloading', data);
  
          toLoad.toLoad.forEach(function (name) {
            var _name$split3 = name.split('|'),
                _name$split4 = _slicedToArray(_name$split3, 2),
                l = _name$split4[0],
                n = _name$split4[1];
  
            var bundle = utils.getPath(data, [l, n]);
            if (bundle) {
              _this5.loaded(name, err, bundle);
            } else {
              var _err = 'loading namespace ' + n + ' for language ' + l + ' via multiloading failed';
              _this5.loaded(name, _err);
              _this5.logger.error(_err);
            }
          });
        });
      }
  
      // load one by one
      else {
          (function () {
            var readOne = function readOne(name) {
              var _this6 = this;
  
              var _name$split5 = name.split('|'),
                  _name$split6 = _slicedToArray(_name$split5, 2),
                  lng = _name$split6[0],
                  ns = _name$split6[1];
  
              this.read(lng, ns, 'read', null, null, function (err, data) {
                if (err) _this6.logger.warn('loading namespace ' + ns + ' for language ' + lng + ' failed', err);
                if (!err && data) _this6.logger.log('loaded namespace ' + ns + ' for language ' + lng, data);
  
                _this6.loaded(name, err, data);
              });
            };
  
            ;
  
            toLoad.toLoad.forEach(function (name) {
              readOne.call(_this5, name);
            });
          })();
        }
    };
  
    Connector.prototype.reload = function reload(languages, namespaces) {
      var _this7 = this;
  
      if (!this.backend) {
        this.logger.warn('No backend was added via i18next.use. Will not load resources.');
      }
      var options = _extends({}, this.backend.options, this.options.backend);
  
      if (typeof languages === 'string') languages = this.services.languageUtils.toResolveHierarchy(languages);
      if (typeof namespaces === 'string') namespaces = [namespaces];
  
      // load with multi-load
      if (options.allowMultiLoading && this.backend.readMulti) {
        this.read(languages, namespaces, 'readMulti', null, null, function (err, data) {
          if (err) _this7.logger.warn('reloading namespaces ' + namespaces.join(', ') + ' for languages ' + languages.join(', ') + ' via multiloading failed', err);
          if (!err && data) _this7.logger.log('reloaded namespaces ' + namespaces.join(', ') + ' for languages ' + languages.join(', ') + ' via multiloading', data);
  
          languages.forEach(function (l) {
            namespaces.forEach(function (n) {
              var bundle = utils.getPath(data, [l, n]);
              if (bundle) {
                _this7.loaded(l + '|' + n, err, bundle);
              } else {
                var _err2 = 'reloading namespace ' + n + ' for language ' + l + ' via multiloading failed';
                _this7.loaded(l + '|' + n, _err2);
                _this7.logger.error(_err2);
              }
            });
          });
        });
      }
  
      // load one by one
      else {
          (function () {
            var readOne = function readOne(name) {
              var _this8 = this;
  
              var _name$split7 = name.split('|'),
                  _name$split8 = _slicedToArray(_name$split7, 2),
                  lng = _name$split8[0],
                  ns = _name$split8[1];
  
              this.read(lng, ns, 'read', null, null, function (err, data) {
                if (err) _this8.logger.warn('reloading namespace ' + ns + ' for language ' + lng + ' failed', err);
                if (!err && data) _this8.logger.log('reloaded namespace ' + ns + ' for language ' + lng, data);
  
                _this8.loaded(name, err, data);
              });
            };
  
            ;
  
            languages.forEach(function (l) {
              namespaces.forEach(function (n) {
                readOne.call(_this7, l + '|' + n);
              });
            });
          })();
        }
    };
  
    Connector.prototype.saveMissing = function saveMissing(languages, namespace, key, fallbackValue) {
      if (this.backend && this.backend.create) this.backend.create(languages, namespace, key, fallbackValue);
  
      // write to store to avoid resending
      if (!languages || !languages[0]) return;
      this.store.addResource(languages[0], namespace, key, fallbackValue);
    };
  
    return Connector;
  }(EventEmitter);
  
  export default Connector;