'use strict';

const SharedObject = require('./shared-object');
const map = require('../operations/map');
const dataValues = require('./data-values');

class SharedMap extends SharedObject {

	constructor(editor) {
		super(editor);

		this.values = {};

		this._apply({
			operation: editor.current
		});
		editor.apply = this._apply.bind(this);
	}

	_apply(data) {
		data.operation.apply({
			remove: (id, oldValue) => {
				const old = this.values[id];
				delete this.values[id];

				this.editor.queueEvent('valueRemoved', {
					key: id,
					oldValue: old
				});
			},

			set: (id, oldValue, newValue) => {
				const value = dataValues.fromData(this.editor, newValue);
				const old = this.values[id];
				this.values[id] = value;

				this.editor.queueEvent('valueChanged', {
					key: id,
					oldValue: old,
					newValue: value
				});
			}
		});
	}

	containsKey(key) {
		return typeof this.values[key] !== 'undefined';
	}

	get(key, factory) {
		let value = this.values[key];
		if(value) return value;

		if(factory) {
			const model = this.editor.model;
			model.performEdit(() => {
				value = this.values[key] = factory(model);

				this.editor.send(map.delta()
					.set(key, dataValues.toData(null), dataValues.toData(value))
					.done()
				);
			});
		}

		return value || null;
	}

	remove(key) {
		const old = this.values[key];
		if(typeof old !== 'undefined') {
			this.editor.send(map.delta()
				.set(key, dataValues.toData(null))
			);
		}
	}

	set(key, value) {
		if(value === null || typeof value === 'undefined') {
			throw new Error('Value must not be null or undefined');
		}

		const old = this.values[key];
		this.editor.send(map.delta()
			.set(key, dataValues.toData(old), dataValues.toData(value))
			.done()
		);
	}
}

module.exports = SharedMap;

@@ -246,10 +246,17 @@
 s = 
-%7B%7D
+new Map()
 ;%0A%0A%09
@@ -453,25 +453,22 @@
 lues
-%5Bid%5D
+.get(id)
 ;%0A%09%09%09%09
-delete 
 this
@@ -474,20 +474,27 @@
 s.values
-%5Bid%5D
+.delete(id)
 ;%0A%0A%09%09%09%09t
@@ -708,20 +708,24 @@
 s.values
-%5Bid%5D
+.get(id)
 ;%0A%09%09%09%09th
@@ -737,20 +737,23 @@
 lues
-%5Bid%5D =
+.set(id,
  value
+)
 ;%0A%0A%09
@@ -990,29 +990,33 @@
  this.values
-%5Bkey%5D
+.get(key)
 ;%0A%09%09if(value
@@ -1117,24 +1117,16 @@
 %3E %7B%0A%09%09%09%09
-value = 
 this.val
@@ -1128,21 +1128,31 @@
 s.values
-%5Bkey%5D
+.set(key, value
  = facto
@@ -1160,16 +1160,17 @@
 y(model)
+)
 ;%0A%0A%09%09%09%09t
@@ -1359,29 +1359,33 @@
  this.values
-%5Bkey%5D
+.get(key)
 ;%0A%09%09if(typeo
@@ -1657,21 +1657,25 @@
 s.values
-%5Bkey%5D
+.get(key)
 ;%0A%09%09this

Use Map in SharedMap instead of Object