function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
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, _toPropertyKey(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 _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
import { collab, getVersion, receiveTransaction, sendableSteps } from 'prosemirror-collab';
import { Plugin, EditorState } from 'prosemirror-state';
import { Step } from 'prosemirror-transform';
import { EditorView } from 'prosemirror-view';
import uuid from '../uuid.js';
import { GET, POST, PUT } from './http.js';
// [FS] IRAD-1040 2020-09-02
import { Schema } from 'prosemirror-model';
import { stringify } from 'flatted';
function badVersion(err) {
  return err.status == 400 && /invalid version/i.test(String(err));
}
var State = /*#__PURE__*/_createClass(function State(edit, comm) {
  _classCallCheck(this, State);
  _defineProperty(this, "edit", void 0);
  _defineProperty(this, "comm", void 0);
  this.edit = edit;
  this.comm = comm;
});
var EditorConnection = /*#__PURE__*/function () {
  function EditorConnection(onReady, report, url, plugins, defaultSchema) {
    var _this = this;
    _classCallCheck(this, EditorConnection);
    _defineProperty(this, "backOff", void 0);
    _defineProperty(this, "onReady", void 0);
    _defineProperty(this, "ready", void 0);
    _defineProperty(this, "report", void 0);
    _defineProperty(this, "request", void 0);
    _defineProperty(this, "state", void 0);
    _defineProperty(this, "url", void 0);
    _defineProperty(this, "view", void 0);
    _defineProperty(this, "schema", void 0);
    _defineProperty(this, "plugins", void 0);
    _defineProperty(this, "defaultSchema", void 0);
    // All state changes go through this
    _defineProperty(this, "dispatch", function (action) {
      var newEditState = null;
      if (action.type == 'loaded') {
        var editState = EditorState.create({
          doc: action.doc,
          plugins: _this.plugins.concat([collab({
            clientID: uuid(),
            version: action.version
          })])
        });
        _this.state = new State(editState, 'poll');
        _this.ready = true;
        _this.onReady(editState);
        _this.poll();
      } else if (action.type == 'restart') {
        _this.state = new State(null, 'start');
        _this.start();
      } else if (action.type == 'poll') {
        _this.state = new State(_this.state.edit, 'poll');
        _this.poll();
      } else if (action.type == 'recover') {
        if (action.error.status && action.error.status < 500) {
          _this.report.failure(action.error);
          _this.state = new State(null, null);
        } else {
          _this.state = new State(_this.state.edit, 'recover');
          _this.recover(action.error);
        }
      } else if (action.type == 'transaction') {
        newEditState = _this.state.edit ? _this.state.edit.apply(action.transaction) : null;
      }
      if (newEditState) {
        var sendable;
        if (newEditState.doc.content.size > 4000000000000) {
          if (_this.state.comm !== 'detached') {
            _this.report.failure('Document too big. Detached.');
          }
          _this.state = new State(newEditState, 'detached');
        } else if ((_this.state.comm == 'poll' || action.requestDone) && (sendable = _this.sendable(newEditState))) {
          _this.closeRequest();
          _this.state = new State(newEditState, 'send');
          _this.send(newEditState, sendable);
        } else if (action.requestDone) {
          _this.state = new State(newEditState, 'poll');
          _this.poll();
        } else {
          _this.state = new State(newEditState, _this.state.comm);
        }
      }

      // Sync the editor with this.state.edit
      if (_this.state.edit && _this.view) {
        _this.view.updateState(_this.state.edit);
      }
    });
    this.schema = null;
    this.report = report;
    this.url = url;
    this.state = new State(null, 'start');
    this.request = null;
    this.backOff = 0;
    this.view = null;
    this.dispatch = this.dispatch.bind(this);
    this.ready = false;
    this.onReady = onReady;
    this.plugins = plugins;
    this.defaultSchema = defaultSchema;
  }

  // [FS] IRAD-1040 2020-09-08
  return _createClass(EditorConnection, [{
    key: "getEffectiveSchema",
    value: function getEffectiveSchema() {
      return null != this.schema ? this.schema : this.defaultSchema;
    }
  }, {
    key: "dispatchData",
    value: function dispatchData(data) {
      this.report.success();
      this.backOff = 0;
      this.dispatch({
        type: 'loaded',
        doc: this.getEffectiveSchema().nodeFromJSON(data),
        version: data.version,
        users: data.users
      });
    }

    // Load the document from the server and start up
  }, {
    key: "start",
    value: function start(input, dataDefined) {
      var _this2 = this;
      var query = '?dataDefined=' + dataDefined;
      this.run(input ? PUT(this.url + query, JSON.stringify(input), 'application/json') : GET(this.url, 'application/json')).then(function (data) {
        data = JSON.parse(data);
        _this2.report.success();
        _this2.backOff = 0;
        _this2.dispatch({
          type: 'loaded',
          doc: _this2.getEffectiveSchema().nodeFromJSON(data.doc_json),
          version: data.version,
          users: data.users
        });
      }, function (err) {
        _this2.report.failure(err);
      });
    }

    // Send a request for events that have happened since the version
    // of the document that the client knows about. This request waits
    // for a new version of the document to be created if the client
    // is already up-to-date.
  }, {
    key: "poll",
    value: function poll() {
      var _this3 = this;
      var query = 'version=' + getVersion(this.state.edit);
      this.run(GET(this.url + '/events?' + query)).then(function (data) {
        _this3.report.success();
        data = JSON.parse(data);
        _this3.backOff = 0;
        if (data.steps && data.steps.length) {
          var tr = receiveTransaction(_this3.state.edit, data.steps.map(function (j) {
            return Step.fromJSON(_this3.getEffectiveSchema(), j);
          }), data.clientIDs);
          _this3.dispatch({
            type: 'transaction',
            transaction: tr,
            requestDone: true
          });
        } else {
          _this3.poll();
        }
      }, function (err) {
        if (err.status == 410 || badVersion(err)) {
          // Too far behind. Revert to server state
          _this3.report.failure(err);
          _this3.dispatch({
            type: 'restart'
          });
        } else if (err) {
          _this3.dispatch({
            type: 'recover',
            error: err
          });
        }
      });
    }
  }, {
    key: "sendable",
    value: function sendable(editState) {
      var steps = sendableSteps(editState);
      if (steps) {
        return {
          steps: steps
        };
      }
      return null;
    }

    // Send the given steps to the server
  }, {
    key: "send",
    value: function send(editState, sendable) {
      var _this4 = this;
      var steps = sendable.steps;
      var json = JSON.stringify({
        version: getVersion(editState),
        steps: steps ? steps.steps.map(function (s) {
          return s.toJSON();
        }) : [],
        clientID: steps ? steps.clientID : 0
      });
      this.run(POST(this.url + '/events', json, 'application/json')).then(function (data) {
        _this4.report.success();
        _this4.backOff = 0;
        var tr = steps ? receiveTransaction(_this4.state.edit, steps.steps, repeat(steps.clientID, steps.steps.length)) : _this4.state.edit.tr;
        _this4.dispatch({
          type: 'transaction',
          transaction: tr,
          requestDone: true
        });
      }, function (err) {
        if (err.status == 409) {
          // The client's document conflicts with the server's version.
          // Poll for changes and then try again.
          _this4.backOff = 0;
          _this4.dispatch({
            type: 'poll'
          });
        } else if (badVersion(err)) {
          _this4.report.failure(err);
          _this4.dispatch({
            type: 'restart'
          });
        } else {
          _this4.dispatch({
            type: 'recover',
            error: err
          });
        }
      });
    }

    // [FS] IRAD-1040 2020-09-02
    // Send the modified schema to server
  }, {
    key: "updateSchema",
    value: function updateSchema(schema, input, dataDefined) {
      var _this5 = this;
      // to avoid cyclic reference error, use flatted string.
      var schemaFlatted = stringify(schema);
      this.run(POST(this.url + '/schema/', schemaFlatted, 'text/plain')).then(function (data) {
        console.log("collab server's schema updated");
        // [FS] IRAD-1040 2020-09-08
        _this5.schema = schema;
        _this5.start(input, dataDefined);
      }, function (err) {
        _this5.report.failure(err);
      });
    }

    // Try to recover from an error
  }, {
    key: "recover",
    value: function recover(err) {
      var _this6 = this;
      var newBackOff = this.backOff ? Math.min(this.backOff * 2, 6e4) : 200;
      if (newBackOff > 1000 && this.backOff < 1000) {
        this.report.delay(err);
      }
      this.backOff = newBackOff;
      setTimeout(function () {
        if (_this6.state.comm == 'recover') {
          _this6.dispatch({
            type: 'poll'
          });
        }
      }, this.backOff);
    }
  }, {
    key: "closeRequest",
    value: function closeRequest() {
      if (this.request) {
        this.request.abort();
        this.request = null;
      }
    }
  }, {
    key: "run",
    value: function run(request) {
      return this.request = request;
    }
  }, {
    key: "close",
    value: function close() {
      this.closeRequest();
      this.setView(null);
    }
  }, {
    key: "setView",
    value: function setView(view) {
      if (this.view) {
        this.view.destroy();
      }
      this.view = window.view = view;
    }
  }]);
}();
function repeat(val, n) {
  var result = [];
  for (var i = 0; i < n; i++) {
    result.push(val);
  }
  return result;
}
export default EditorConnection;