var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
var _CoreManager = _interopRequireDefault(require("./CoreManager"));
var _ParseObject = _interopRequireDefault(require("./ParseObject"));
var _ParseQuery = _interopRequireDefault(require("./ParseQuery"));
var _Storage = _interopRequireDefault(require("./Storage"));
var QUEUE_KEY = 'Parse/Eventually/Queue';
var queueCache = [];
var dirtyCache = true;
var polling = undefined;
var EventuallyQueue = {
  save: function (object) {
    var serverOptions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
    return this.enqueue('save', object, serverOptions);
  },
  destroy: function (object) {
    var serverOptions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
    return this.enqueue('destroy', object, serverOptions);
  },
  generateQueueId: function (action, object) {
    object._getId();
    var className = object.className,
      id = object.id,
      _localId = object._localId;
    var uniqueId = object.get('hash') || _localId;
    return [action, className, id, uniqueId].join('_');
  },
  enqueue: function () {
    var _enqueue = (0, _asyncToGenerator2.default)(function* (action, object, serverOptions) {
      var queueData = yield this.getQueue();
      var queueId = this.generateQueueId(action, object);
      var index = this.queueItemExists(queueData, queueId);
      if (index > -1) {
        for (var prop in queueData[index].object) {
          if (typeof object.get(prop) === 'undefined') {
            object.set(prop, queueData[index].object[prop]);
          }
        }
      } else {
        index = queueData.length;
      }
      queueData[index] = {
        queueId: queueId,
        action: action,
        object: object.toJSON(),
        serverOptions: serverOptions,
        id: object.id,
        className: object.className,
        hash: object.get('hash'),
        createdAt: new Date()
      };
      return this.setQueue(queueData);
    });
    function enqueue() {
      return _enqueue.apply(this, arguments);
    }
    return enqueue;
  }(),
  store: function (data) {
    return _Storage.default.setItemAsync(QUEUE_KEY, JSON.stringify(data));
  },
  load: function () {
    return _Storage.default.getItemAsync(QUEUE_KEY);
  },
  getQueue: function () {
    var _getQueue = (0, _asyncToGenerator2.default)(function* () {
      if (dirtyCache) {
        queueCache = JSON.parse((yield this.load()) || '[]');
        dirtyCache = false;
      }
      return queueCache;
    });
    function getQueue() {
      return _getQueue.apply(this, arguments);
    }
    return getQueue;
  }(),
  setQueue: function (queue) {
    queueCache = queue;
    return this.store(queueCache);
  },
  remove: function () {
    var _remove = (0, _asyncToGenerator2.default)(function* (queueId) {
      var queueData = yield this.getQueue();
      var index = this.queueItemExists(queueData, queueId);
      if (index > -1) {
        queueData.splice(index, 1);
        yield this.setQueue(queueData);
      }
    });
    function remove() {
      return _remove.apply(this, arguments);
    }
    return remove;
  }(),
  clear: function () {
    queueCache = [];
    return this.store([]);
  },
  queueItemExists: function (queue, queueId) {
    return queue.findIndex(function (data) {
      return data.queueId === queueId;
    });
  },
  length: function () {
    var _length = (0, _asyncToGenerator2.default)(function* () {
      var queueData = yield this.getQueue();
      return queueData.length;
    });
    function length() {
      return _length.apply(this, arguments);
    }
    return length;
  }(),
  sendQueue: function () {
    var _sendQueue = (0, _asyncToGenerator2.default)(function* () {
      var queue = yield this.getQueue();
      var queueData = (0, _toConsumableArray2.default)(queue);
      if (queueData.length === 0) {
        return false;
      }
      for (var i = 0; i < queueData.length; i += 1) {
        var queueObject = queueData[i];
        var id = queueObject.id,
          hash = queueObject.hash,
          className = queueObject.className;
        var ObjectType = _ParseObject.default.extend(className);
        if (id) {
          yield this.process.byId(ObjectType, queueObject);
        } else if (hash) {
          yield this.process.byHash(ObjectType, queueObject);
        } else {
          yield this.process.create(ObjectType, queueObject);
        }
      }
      return true;
    });
    function sendQueue() {
      return _sendQueue.apply(this, arguments);
    }
    return sendQueue;
  }(),
  sendQueueCallback: function () {
    var _sendQueueCallback = (0, _asyncToGenerator2.default)(function* (object, queueObject) {
      if (!object) {
        return this.remove(queueObject.queueId);
      }
      switch (queueObject.action) {
        case 'save':
          if (typeof object.updatedAt !== 'undefined' && object.updatedAt > new Date(queueObject.object.createdAt)) {
            return this.remove(queueObject.queueId);
          }
          try {
            yield object.save(queueObject.object, queueObject.serverOptions);
            yield this.remove(queueObject.queueId);
          } catch (e) {
            if (e.message !== 'XMLHttpRequest failed: "Unable to connect to the Parse API"') {
              yield this.remove(queueObject.queueId);
            }
          }
          break;
        case 'destroy':
          try {
            yield object.destroy(queueObject.serverOptions);
            yield this.remove(queueObject.queueId);
          } catch (e) {
            if (e.message !== 'XMLHttpRequest failed: "Unable to connect to the Parse API"') {
              yield this.remove(queueObject.queueId);
            }
          }
          break;
      }
    });
    function sendQueueCallback() {
      return _sendQueueCallback.apply(this, arguments);
    }
    return sendQueueCallback;
  }(),
  poll: function () {
    var _this = this;
    var ms = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 2000;
    if (polling) {
      return;
    }
    polling = setInterval(function () {
      var RESTController = _CoreManager.default.getRESTController();
      RESTController.request('GET', 'health').then(function (_ref) {
        var status = _ref.status;
        if (status === 'ok') {
          _this.stopPoll();
          return _this.sendQueue();
        }
      }).catch(function (e) {
        return e;
      });
    }, ms);
  },
  stopPoll: function () {
    clearInterval(polling);
    polling = undefined;
  },
  isPolling: function () {
    return !!polling;
  },
  _setPolling: function (flag) {
    polling = flag;
  },
  process: {
    create: function (ObjectType, queueObject) {
      var object = new ObjectType();
      return EventuallyQueue.sendQueueCallback(object, queueObject);
    },
    byId: function () {
      var _byId = (0, _asyncToGenerator2.default)(function* (ObjectType, queueObject) {
        var sessionToken = queueObject.serverOptions.sessionToken;
        var query = new _ParseQuery.default(ObjectType);
        query.equalTo('objectId', queueObject.id);
        var results = yield query.find({
          sessionToken: sessionToken
        });
        return EventuallyQueue.sendQueueCallback(results[0], queueObject);
      });
      function byId() {
        return _byId.apply(this, arguments);
      }
      return byId;
    }(),
    byHash: function () {
      var _byHash = (0, _asyncToGenerator2.default)(function* (ObjectType, queueObject) {
        var sessionToken = queueObject.serverOptions.sessionToken;
        var query = new _ParseQuery.default(ObjectType);
        query.equalTo('hash', queueObject.hash);
        var results = yield query.find({
          sessionToken: sessionToken
        });
        if (results.length > 0) {
          return EventuallyQueue.sendQueueCallback(results[0], queueObject);
        }
        return EventuallyQueue.process.create(ObjectType, queueObject);
      });
      function byHash() {
        return _byHash.apply(this, arguments);
      }
      return byHash;
    }()
  }
};
module.exports = EventuallyQueue;