"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 _akutils = require("akutils");

var _createPropertyClass = require("./createPropertyClass");

var _createPropertyClass2 = _interopRequireDefault(_createPropertyClass);

var _IsolatedObjectShadowImpl = require("./IsolatedObjectShadowImpl");

var _IsolatedObjectShadowImpl2 = _interopRequireDefault(_IsolatedObjectShadowImpl);

var _KeyedApi = require("./KeyedApi");

var _KeyedApi2 = _interopRequireDefault(_KeyedApi);

var _ObjectShadowImpl = require("./ObjectShadowImpl");

var _ObjectShadowImpl2 = _interopRequireDefault(_ObjectShadowImpl);

var _Property2 = require("./Property");

var _Property3 = _interopRequireDefault(_Property2);

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

var _Shadow2 = _interopRequireDefault(_Shadow);

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

var _StateType2 = _interopRequireDefault(_StateType);

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

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

/**
	A generic object property type that supports keyed child properties access.

	The default shadow class is {@link Shadow}.

	Use `ObjectProperty` when you want to place a full custom API on a javascript object or just want
	an object without any methods. By default, properties can be accessed/updated using dot syntax and
	the shadow does not provide any access or property manipulation methods.

	The `_keyed` instance variable exposes a {@link KeyedApi} instance for working with properties.
	Readonly properties cannot be updated using the shadow so the `this._keyed` is used set the value
	or remove it from the object. For example,

	```js
	this._keyed.set("updated", Date());
	```
	would set the `updated` shadow property with a string value for the current time.

	@see {@link KeyedApi}
	@see {@link Shadow}
*/

var ObjectProperty = function (_Property) {
	_inherits(ObjectProperty, _Property);

	/**
 	If a {@link StateType} is not passed to this constructor then one is located using
 	{@link StateType.from} thus ensuring the f.lux shadowing process is defined for this
 	property.
 		@param {StateType} [stateType] - a specialized {@link StateType} instance describing how f.lux should
 		shadow this property.
 */

	function ObjectProperty(stateType) {
		_classCallCheck(this, ObjectProperty);

		var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(ObjectProperty).call(this, stateType));

		_this._keyed = new _KeyedApi2.default(_this);

		if (_this.stateType().isIsolated()) {
			_this.setImplementationClass(_IsolatedObjectShadowImpl2.default);
		} else {
			_this.setImplementationClass(_ObjectShadowImpl2.default);
		}

		_this.setShadowClass(_Shadow2.default);
		return _this;
	}

	/**
 	Factory function for creating an `ObjectProperty` subclass. The generated class will have
 	the `type` {@link StateType} descriptor set upon return.
 		Example usage:
 	```
 	class UiShadow extends Shadow {
 	    // definition here
 	}
 		export default ObjectProperty.createClass(UiShadow, type => {
 		// configure type variable
 	});
 	```
 		@param {Object|Shadow} [shadowType={}] - `Shadow` subclass or object literal api definition.
 		If object literal specified, each property and function is mapped onto a Shadow subclass.
 	@param {function(type: StateType)} [typeCallback] - a callback function that will be passed the
 		{@link StateType} spec for additional customization, such as setting autoshadow, initial state,
 		or readonly.
 	@param {Object} [initialState]={} - the initial state for the new property.
 		@return {ObjectProperty} newly defined `ObjectProperty` subclass.
 */


	_createClass(ObjectProperty, null, [{
		key: "createClass",
		value: function createClass() {
			var shadowType = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
			var typeCallback = arguments[1];
			var initialState = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];

			return (0, _createPropertyClass2.default)(shadowType, initialState, typeCallback, ObjectProperty);
		}

		/**
  	Factory function for setting up the {@link StateType} `type` class variable with an appropriately
  	configured intial state.
  		Example usage:
  	```
         export default class TodoProperty extends ObjectProperty {
  		// implement property here
         }
          class TodoShadow extends Shadow {
  		// implement shadow api here
         }
          ObjectProperty.defineType(TodoProperty, TodoShadow, type => {
  		// configure type variable
         });
  	```
  		@param {ObjectProperty} PropClass - `ObjectProperty` subclass
  	@param {Object|Shadow} [ShadowType] - Shadow` subclass or object literal api definition.
  		If object literal specified, each property and function is mapped onto a Shadow subclass.
  	@param {function(type: StateType)} [typeCallback] - a callback function that will be passed the
  		{@link StateType} spec for additional customization, such as setting autoshadow, initial state, or
  		readonly.
  	@param {Object} [initialState={}] - the initial state for the new property.
  */

	}, {
		key: "defineType",
		value: function defineType(PropClass, ShadowType, typeCallback) {
			var initialState = arguments.length <= 3 || arguments[3] === undefined ? {} : arguments[3];

			(0, _akutils.assert)(function (a) {
				return a.is(ObjectProperty.isPrototypeOf(PropClass), "PropClass must subclass ObjectProperty");
			});

			_StateType2.default.defineTypeEx(PropClass, ShadowType, typeCallback, initialState);
		}

		/**
  	Used by {@link StateType} to determine if a keyed property type.
  		@ignore
  */

	}, {
		key: "supportsKeyedChildProperties",
		value: function supportsKeyedChildProperties() {
			return true;
		}
	}]);

	return ObjectProperty;
}(_Property3.default);

exports.default = ObjectProperty;


_StateType2.default.defineType(ObjectProperty, function (spec) {
	return spec.initialState({}).typeName("ObjectProperty");
});