'use strict';

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

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

var _fluxEditorActions = require('../flux/EditorActions');

var _fluxEditorActions2 = _interopRequireDefault(_fluxEditorActions);

exports['default'] = {
  createSharedCursor: function createSharedCursor() {
    var Swarm = this.swarmClient.Swarm;

    this.cursorId = this.props.id + '_' + this.swarmClient.id;
    this.cursorSet = new Swarm.CursorSet('/CursorSet#' + this.props.id);

    this.trackedCursors = {};

    this.cursorSet.on('.init', this.onCursorSetInitialize);
    this.cursorSet.on('.change', this.onCursorSet);
  },

  onCursorSetInitialize: function onCursorSetInitialize(spec, value, source) {
    var _this = this;

    // eslint-disable-line no-unused-vars
    var Swarm = this.swarmClient.Swarm;

    this.cursorModel = new Swarm.CursorModel(this.cursorId);
    this.cursorModel.set({
      name: this.props.userName
    });

    this.cursorSet.addObject(this.cursorModel);
    // if we lose connection to the server and then gain it again, add the cursor model to the cursor set again
    this.swarmClient.addReonHook(function () {
      _this.cursorSet.addObject(_this.cursorModel);
    });
    this.swarmClient.addUnloadHook(function () {
      _this.cursorSet.removeObject(_this.cursorModel);
      Object.keys(_this.trackedCursors).forEach(function (cursorId) {
        return _this.unSubscribeRemoteCursor(_this.trackedCursors[cursorId]);
      });
      _this.cursorSet.off('.init', _this.onCursorSetInitialize);
      _this.cursorSet.off('.change', _this.onCursorSet);
    });

    _fluxEditorActions2['default'].initializeCursorModel(this.cursorSet, this.cursorModel);

    // setup the initial remote cursors
    this.onCursorSet(spec, value, source);
  },

  onCursorSet: function onCursorSet(spec, value, source) {
    var _this2 = this;

    // eslint-disable-line no-unused-vars
    if (spec.op() === 'init') {
      this.foreignCursorSet().forEach(function (remoteCursorModel) {
        _this2.subscribeRemoteCursor(remoteCursorModel);
      });
    } else if (spec.op() === 'change') {
      Object.keys(value).forEach(function (objectSpec) {
        var op = value[objectSpec];
        var remoteCursorModel = _this2.swarmClient.host.get(objectSpec);
        // ignore set changes to our own cursor
        if (remoteCursorModel._id !== _this2.cursorId) {
          if (op === 0 && _this2.trackedCursors[remoteCursorModel._id]) {
            // delete
            _this2.unSubscribeRemoteCursor(_this2.trackedCursors[remoteCursorModel._id]);
          } else if (op === 1) {
            // add
            _this2.subscribeRemoteCursor(remoteCursorModel);
          }
        }
      });
    }
  },

  subscribeRemoteCursor: function subscribeRemoteCursor(remoteCursorModel) {
    var _this3 = this;

    var id = remoteCursorModel._id;
    var remoteCursor = undefined;
    // if already subscribed, unsubscribe first (but keep the local info) --> shouldn't happen but check for it anyway
    if (this.trackedCursors[id]) {
      remoteCursor = this.trackedCursors[id];
      remoteCursor.model.off('.set', this.onRemoteCursorUpdate);
      remoteCursor.model = remoteCursorModel;
    } else {
      (function () {
        var usedColors = new Set(Object.keys(_this3.trackedCursors).map(function (cursorId) {
          return _this3.trackedCursors[cursorId].color;
        }));
        var possibleColors = _this3.props.cursorColorSpace.filter(function (c) {
          return !usedColors.has(c);
        });
        // re-use colors if none are left
        var color = possibleColors.length > 0 ? possibleColors[0] : usedColors[0];
        remoteCursor = {
          model: remoteCursorModel,
          color: color
        };
        _this3.trackedCursors[id] = remoteCursor;
      })();
    }
    _fluxEditorActions2['default'].setRemoteCursorPosition(remoteCursor);
    remoteCursorModel.on('.set', this.onRemoteCursorUpdate);
  },

  unSubscribeRemoteCursor: function unSubscribeRemoteCursor(remoteCursor) {
    var id = remoteCursor.model._id;
    // TODO this doesn't work because swarm.js is looking for the function in listener.sink but it is found in listener.sink.sink
    // see https://github.com/gritzko/swarm/blob/master/lib/Syncable.js#L673
    remoteCursor.model.off('.set', this.onRemoteCursorUpdate);
    delete this.trackedCursors[id];
    _fluxEditorActions2['default'].unsetRemoteCursorPosition(remoteCursor);
  },

  onRemoteCursorUpdate: function onRemoteCursorUpdate(spec, value, source) {
    // eslint-disable-line no-unused-vars
    var id = source._id;
    if (!id || !this.trackedCursors[id]) return;
    _fluxEditorActions2['default'].setRemoteCursorPosition(this.trackedCursors[id]);
  },

  foreignCursorSet: function foreignCursorSet() {
    var _this4 = this;

    return this.cursorSet.list().filter(function (c) {
      return c._id && c._id !== _this4.cursorId;
    });
  }
};
module.exports = exports['default'];