"use strict";

exports.__esModule = true;
exports.default = 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 _es6Symbol = require("es6-symbol");

var _es6Symbol2 = _interopRequireDefault(_es6Symbol);

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

var _lodash2 = _interopRequireDefault(_lodash);

var _akutils = require("akutils");

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

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

/**
	API implementation for properties that support keyed access to child properties.

	@see {@link MapProperty}
	@see {@link ObjectProperty}
*/

var KeyedApi = function () {
	function KeyedApi(property) {
		_classCallCheck(this, KeyedApi);

		this._property = property;
	}

	_createClass(KeyedApi, [{
		key: "impl",
		value: function impl() {
			return this._property.__();
		}
	}, {
		key: "isActive",
		value: function isActive() {
			return this._property.isActive();
		}
	}, {
		key: "shadow",
		value: function shadow() {
			return this._property._();
		}
	}, {
		key: "addProperty",
		value: function addProperty(name, property, automount) {
			property.setParent(this._property);

			return this.addPropertyShader(name, property.shader(), property.getInitialState(), automount);
		}
	}, {
		key: "addPropertyType",
		value: function addPropertyType(name, stateType) {
			return this.addPropertyShader(name, stateType.factory(this._property), stateType._initialState);
		}
	}, {
		key: "addPropertyShader",
		value: function addPropertyShader(name, shader, initialState, automount) {
			var property = this._property;
			var propInitialState = property.initialState();

			// initial state has two sources: parameter and the shader
			var iState = initialState !== undefined ? initialState : shader.initialState ? shader.initialState : propInitialState && propInitialState[name];

			property.shader().add(name, shader, automount);

			if (this.isActive()) {
				if (iState !== undefined) {
					this.set(name, iState);
				}

				property.touch();
			} else if (propInitialState) {
				propInitialState[name] = iState;
			}

			// return shader so can be further customized
			return shader;
		}
	}, {
		key: "removeProperty",
		value: function removeProperty(name) {
			this._property.shader().remove(name);
			this.delete(name);
		}

		//------------------------------------------------------------------------------------------------------
		// Map and other useful data structure functions
		//------------------------------------------------------------------------------------------------------

	}, {
		key: "clear",
		value: function clear() {
			if (this.isActive()) {
				this.impl().clear();
			}
		}
	}, {
		key: "delete",
		value: function _delete(key) {
			if (this.isActive()) {
				var value = this.shadow()[key];

				// need to perform action even if value is undefined because could be a queued action
				// to add it.
				this.impl().delete(key);

				return value;
			}
		}
	}, {
		key: "entries",
		value: function entries() {
			var _this = this;

			if (!this.isActive()) {
				return _akutils.doneIterator;
			}

			return (0, _akutils.iterateOver)(this.keysArray(), function (key) {
				return [key, _this.get(key)];
			});
		}
	}, {
		key: "filter",
		value: function filter(callback, context) {
			var keys = this.keysArray();
			var shadow = this.shadow();
			var acc = [];
			var key, value;

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

				if (callback.call(context, value, key, shadow)) {
					acc.push(value);
				}
			}

			return acc;
		}
	}, {
		key: "get",
		value: function get(key) {
			if (this.isActive()) {
				return this.shadow()[key];
			}
		}
	}, {
		key: "has",
		value: function has(key) {
			if (this.isActive()) {
				return (0, _lodash2.default)(this.shadow(), key);
			}
		}
	}, {
		key: "keys",
		value: function keys() {
			if (!this.isActive()) {
				return _akutils.doneIterator;
			}

			return (0, _akutils.iteratorFor)(this.keysArray());
		}
	}, {
		key: "keysArray",
		value: function keysArray() {
			if (!this.isActive()) {
				return [];
			}

			// use Object.keys() so do not get non-enumerable properties
			return Object.keys(this.shadow());
		}
	}, {
		key: "set",
		value: function set(key, value) {
			if (this.isActive()) {
				this.impl().set(key, value);
			}
		}

		/*
  	Converting map size property to a function in keeping with current design philosophy of minimizing
  	internal object properties in favor of methods.
  */

	}, {
		key: "size",
		value: function size() {
			return this.impl().size();
		}
	}, {
		key: "valuesArray",
		value: function valuesArray() {
			if (!this.isActive()) {
				return [];
			}

			var shadow = this.shadow();
			var keys = this.keysArray();
			var values = [];

			for (var i = 0, len = keys.length; i < len; i++) {
				values.push(shadow[keys[i]]);
			}

			return values;
		}
	}, {
		key: "values",
		value: function values() {
			var _this2 = this;

			if (!this.isActive()) {
				return _akutils.doneIterator;
			}

			return (0, _akutils.iterateOver)(this.keysArray(), function (key) {
				return _this2.get(key);
			});
		}
	}, {
		key: _es6Symbol2.default.iterator,
		value: function value() {
			return this.entries();
		}
	}]);

	return KeyedApi;
}();

exports.default = KeyedApi;