"use strict";

exports.__esModule = true;
exports.default = exports.TransientShadow = exports.TransientLock = undefined;

var _createClass = function () { 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, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _akutils = require("akutils");

var _es6Symbol = require("es6-symbol");

var _es6Symbol2 = _interopRequireDefault(_es6Symbol);

var _ObjectProperty2 = require("./ObjectProperty");

var _ObjectProperty3 = _interopRequireDefault(_ObjectProperty2);

var _PrimitiveProperty = require("./PrimitiveProperty");

var _PrimitiveProperty2 = _interopRequireDefault(_PrimitiveProperty);

var _Shadow2 = require("./Shadow");

var _Shadow3 = _interopRequireDefault(_Shadow2);

var _StateType = require("./StateType");

var _StateType2 = _interopRequireDefault(_StateType);

var _debug = require("./debug");

var _debug2 = _interopRequireDefault(_debug);

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

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

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) : subClass.__proto__ = superClass; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var debug = (0, _debug2.default)(_debug.TransientKey);

var _data = "data";
var _desc = (0, _es6Symbol2.default)('desc');
var _id = "id";
var _lockId = (0, _es6Symbol2.default)('lockId');
var _locks = (0, _es6Symbol2.default)('locks');
var _subscribers = (0, _es6Symbol2.default)('subscribers');
var _trans = (0, _es6Symbol2.default)('trans');
var _transId = (0, _es6Symbol2.default)('id');
//const PrimaryLockName = "__primary__";

var nextLockId = 1;

var TransientLock = exports.TransientLock = function () {
	function TransientLock(id, desc, trans) {
		_classCallCheck(this, TransientLock);

		this[_lockId] = id;
		this[_desc] = desc;
		this[_trans] = trans;
	}

	_createClass(TransientLock, [{
		key: "desc",
		value: function desc() {
			return this[_desc];
		}
	}, {
		key: "id",
		value: function id() {
			return this[_lockId];
		}
	}, {
		key: "is",
		value: function is(desc) {
			return this[_desc] === desc;
		}
	}, {
		key: "release",
		value: function release() {
			this[_trans]._removeLock(this);
		}
	}, {
		key: "trans",
		value: function trans() {
			return this[_trans];
		}
	}]);

	return TransientLock;
}();

var TransientShadow = exports.TransientShadow = function (_Shadow) {
	_inherits(TransientShadow, _Shadow);

	function TransientShadow() {
		_classCallCheck(this, TransientShadow);

		return _possibleConstructorReturn(this, Object.getPrototypeOf(TransientShadow).apply(this, arguments));
	}

	_createClass(TransientShadow, [{
		key: "delete",
		value: function _delete() {
			var transRoot = this.$$().parent()._();

			transRoot.delete(this.id);
		}
	}, {
		key: "isLocked",
		value: function isLocked() {
			return this.$$().isLocked();
		}
	}, {
		key: "lock",
		value: function lock(desc) {
			return this.$$().lock(desc);
		}
	}]);

	return TransientShadow;
}(_Shadow3.default);

/*

*/


var TransientProperty = function (_ObjectProperty) {
	_inherits(TransientProperty, _ObjectProperty);

	function TransientProperty(id, property) {
		_classCallCheck(this, TransientProperty);

		var _this2 = _possibleConstructorReturn(this, Object.getPrototypeOf(TransientProperty).call(this));

		_this2._keyed.addProperty(_data, property);
		_this2._keyed.set(_id, id);

		_this2.setShadowClass(TransientShadow);
		_this2[_transId] = id;
		_this2[_locks] = [];

		debug(function (d) {
			return d("TransientProperty created: id=" + id);
		});
		return _this2;
	}

	_createClass(TransientProperty, [{
		key: "propertyWillUnshadow",
		value: function propertyWillUnshadow() {
			var _this3 = this;

			delete this[_locks];

			debug(function (d) {
				return d("propertyWillUnshadow(): id=" + _this3[_transId]);
			});
		}
	}, {
		key: "data",
		value: function data() {
			var transObj = this._();

			return transObj && transObj.data;
		}
	}, {
		key: "isLocked",
		value: function isLocked() {
			return this[_locks] && this[_locks].length > 0;
		}
	}, {
		key: "lock",
		value: function lock() {
			var desc = arguments.length <= 0 || arguments[0] === undefined ? "lock:" + nextLockId : arguments[0];

			return this._addLock(new TransientLock(nextLockId++, desc, this));
		}
	}, {
		key: "_removeLock",
		value: function _removeLock(lock) {
			var _this4 = this;

			if (!this[_locks]) {
				return;
			}

			this[_locks] = this[_locks].filter(function (l) {
				return l !== lock;
			});
			debug(function (d) {
				return d("_removeLock(): id=" + _this4[_transId] + ", locked=" + _this4.isLocked() + ", desc=" + lock.desc());
			});
		}
	}, {
		key: "_addLock",
		value: function _addLock(lock) {
			var _this5 = this;

			(0, _akutils.assert)(function (a) {
				return a.is(lock.trans() === _this5, "Lock transient object mismatch");
			});

			if (!this[_locks]) {
				return null;
			}

			this[_locks].push(lock);
			debug(function (d) {
				return d("_addLock(): id=" + _this5[_transId] + ", desc=" + lock.desc());
			});

			return lock;
		}
	}, {
		key: "id",
		get: function get() {
			return this[_transId];
		}
	}]);

	return TransientProperty;
}(_ObjectProperty3.default);

exports.default = TransientProperty;


_StateType2.default.defineType(TransientProperty, function (spec) {
	spec.initialState({}).properties(_defineProperty({}, _id, _PrimitiveProperty2.default.type)).autoshadowOff.readonly.typeName("TransientProperty");
});