"use strict";

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

var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

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 _es6Symbol = require("es6-symbol");

var _es6Symbol2 = _interopRequireDefault(_es6Symbol);

var _lodash = require("lodash.omit");

var _lodash2 = _interopRequireDefault(_lodash);

var _IsolatedProperty = require("./IsolatedProperty");

var _IsolatedProperty2 = _interopRequireDefault(_IsolatedProperty);

var _ShadowImpl2 = require("./ShadowImpl");

var _ShadowImpl3 = _interopRequireDefault(_ShadowImpl2);

var _reshadow = require("./reshadow");

var _reshadow2 = _interopRequireDefault(_reshadow);

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 _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

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; }

var _implsCacheKey = (0, _es6Symbol2.default)("implsCacheKey");
var _keysCacheKey = (0, _es6Symbol2.default)("keysCacheKey");
var _valuesCacheKey = (0, _es6Symbol2.default)("valuesCacheKey");

var IsolatedObjectShadowImpl = function (_ShadowImpl) {
	_inherits(IsolatedObjectShadowImpl, _ShadowImpl);

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

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

	_createClass(IsolatedObjectShadowImpl, [{
		key: "clear",

		/*
  	Removes all subproperties.
  */
		value: function clear() {
			this.isolated().removeAllFor(this.property());
			this.update(function (state) {
				return { name: "clear()", nextState: state };
			});
		}

		/*
  	Removes a subproperty from this state property.
  */

	}, {
		key: "delete",
		value: function _delete(k) {
			this.isolated().remove(k, this.property());
			this.update(function (state) {
				return { name: "delete(" + k + ")", nextState: (0, _lodash2.default)(state, k) };
			});
			//		this.update( state => ({ name: `delete(${k})`, nextState: state }) );
		}

		/*
  	Gets a copy of the implementation objects.
  		@return {object} key=name, value=property
  */

	}, {
		key: "entries",
		value: function entries() {
			return this.isolated().entires(this.property());
		}
	}, {
		key: "extend",
		value: function extend(sources) {
			var keys = Object.keys(sources);
			var key;

			for (var i = 0, len = keys.length; i < len; i++) {
				key = keys[i];

				this.set(key, sources[key]);
			}
		}

		/*
  	Gets the property implementation for a state property.
  */

	}, {
		key: "get",
		value: function get(k) {
			var isoProp = this.isolated().get(k, this.property());
			var isoShadow = isoProp && isoProp._();

			if (isoProp && isoProp.isActive()) {
				return isoProp._().data.__();
			} else {
				return undefined;
			}
		}

		/*
  	Gets if this state property has a subproperty with a specified name.
  */

	}, {
		key: "has",
		value: function has(k) {
			return !!this.get(k);
		}
	}, {
		key: "isolated",
		value: function isolated() {
			return this.store().isolated();
		}

		/*
  	Gets the keys of all managed subproperties. Returns an array.
  */

	}, {
		key: "keys",
		value: function keys() {
			var cache = this.cache();

			if (!cache[_keysCacheKey]) {
				var isoProps = this.isolated().all(this.property());

				cache[_keysCacheKey] = isoProps.map(function (p) {
					return p.name();
				});
			}

			return cache[_keysCacheKey];
		}

		/*
  	Sets a subproperty value. Replaces current state property if one has an identical name.
  */

	}, {
		key: "set",
		value: function set(k, v) {
			this.isolated().set(k, v, this.property());

			this.update(function (state) {
				return { name: "set(" + k + ")", nextState: _extends({}, state, _defineProperty({}, k, { data: v })) };
			});

			return this;
		}
	}, {
		key: "size",
		value: function size() {
			return this.isolated().count(this.property());
		}

		/*
  	Gets subproperty implementation objects. Returns an array.
  */

	}, {
		key: "values",
		value: function values() {
			var cache = this.cache();

			if (!cache[_valuesCacheKey]) {
				var isoProps = this.isolated().all(this.property());

				cache[_valuesCacheKey] = isoProps.map(function (p) {
					return p._().data.__();
				});
			}

			return cache[_valuesCacheKey];
		}

		//------------------------------------------------------------------------------------------------------
		//	Overridden methods
		//------------------------------------------------------------------------------------------------------

	}, {
		key: "childCount",
		value: function childCount() {
			return this.size();
		}
	}, {
		key: "children",
		value: function children() {
			var cache = this.cache();

			if (!cache[_implsCacheKey]) {
				var isoProps = this.isolated().all(this.property());

				cache[_implsCacheKey] = isoProps.map(function (p) {
					return p.__();
				});
			}

			return cache[_implsCacheKey];
		}
	}, {
		key: "defaults",
		value: function defaults(state) {
			console.warn("defaults() not supported");
		}

		/*
  	Maps all child properties onto this property using Object.defineProperty().
  */

	}, {
		key: "defineChildProperties",
		value: function defineChildProperties(prev, inCtor) {
			var _this2 = this;

			var isolated = this.isolated();
			var property = this.property();

			isolated.update(property);

			// get keys after isolated update() since it will alter iso properties
			// explicitly build list based on shader children since this will usually be
			// a much smaller number of items than the number of children
			var shader = this.shader();
			var keys = shader.keys().filter(function (k) {
				return isolated.has(k, property);
			});

			shader.shadowUndefinedProperties(keys, this, function (name, shader) {
				_this2.set(name, shader.stateType().computeInitialState());
			}, keys);

			isolated.update(property);
		}
	}, {
		key: "hasChildren",
		value: function hasChildren() {
			return !!this.size();
		}
	}, {
		key: "merge",
		value: function merge(state) {
			console.warn("merge() not supported");
		}
	}, {
		key: "onObsolete",
		value: function onObsolete() {
			this.isolated().removeOwner(this.property());
		}
	}]);

	return IsolatedObjectShadowImpl;
}(_ShadowImpl3.default);

exports.default = IsolatedObjectShadowImpl;