"use strict";

exports.__esModule = true;
exports.default = exports._dataKey = 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 _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _akutils = require("akutils");

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

var _es6Symbol2 = _interopRequireDefault(_es6Symbol);

var _IsolatedAccess = require("./IsolatedAccess");

var _IsolatedAccess2 = _interopRequireDefault(_IsolatedAccess);

var _IsolatedShadow = require("./IsolatedShadow");

var _IsolatedShadow2 = _interopRequireDefault(_IsolatedShadow);

var _IsolatedShadowImpl = require("./IsolatedShadowImpl");

var _IsolatedShadowImpl2 = _interopRequireDefault(_IsolatedShadowImpl);

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

var _KeyedApi2 = _interopRequireDefault(_KeyedApi);

var _MapProperty = require("./MapProperty");

var _MapProperty2 = _interopRequireDefault(_MapProperty);

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

var _Property3 = _interopRequireDefault(_Property2);

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

// child property names
var _dataKey = exports._dataKey = "data";

// private instance variable symbols
var _id = (0, _es6Symbol2.default)("id");
var _key = (0, _es6Symbol2.default)("key");
var _owner = (0, _es6Symbol2.default)("owner");

/**

*/

var IsolatedProperty = function (_Property) {
	_inherits(IsolatedProperty, _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 IsolatedProperty(stateType) {
		_classCallCheck(this, IsolatedProperty);

		//		assert( a => a.is(stateType.getManagedType(), "Managed type must be set") );

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

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

		_this.setImplementationClass(_IsolatedShadowImpl2.default);
		_this.setShadowClass(_IsolatedShadow2.default);

		var managedType = _this.stateType().getManagedType();
		var shader = _this.shader();

		//		shader.addProperty(_dataKey, managedType);

		_this[_id] = (0, _akutils.uuid)("_");
		return _this;
	}

	/**
 	Factory function for creating an `MapProperty` subclass suitable for using with new. The generated
 	class will have the `type` {@link StateType} descriptor set upon return.
 		Example usage:
 	```
 	class SomeShadow extends MapShadow {
 	    // definition here
 	}
 		export default MapProperty.createClass(SomeShadow, type => {
 		// configure type variable
 	});
 	```
 		@param {Object|IsolatedShadow} [shadowType={}] - `MapShadow` 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 {MapProperty} newly defined `MapProperty` subclass.
 */


	_createClass(IsolatedProperty, [{
		key: "propertyChildInvalidated",


		//------------------------------------------------------------------------------------------------------
		// Life-cycle methods
		//------------------------------------------------------------------------------------------------------

		value: function propertyChildInvalidated(childProperty, sourceProperty) {
			this.store().isolated().invalidated(this);
		}

		//------------------------------------------------------------------------------------------------------
		// Isolated specific methods
		//------------------------------------------------------------------------------------------------------

		/**
  	Gets the ID used by the store to track this isolated property.
  		@return {string}
  */

	}, {
		key: "isolationId",
		value: function isolationId() {
			return this[_id];
		}
	}, {
		key: "key",
		value: function key() {
			return this[_key];
		}

		/**
  	Gets the property managing this isolated object.
  		@return {Property}
  */

	}, {
		key: "owner",
		value: function owner() {
			return this[_owner];
		}
	}, {
		key: "setKey",
		value: function setKey(key) {
			this[_key] = key;
		}

		/**
  	Sets the property that owns/contains this isolated property.
  		@param {Property} owner - the object containing/managing this isolated property.
  */

	}, {
		key: "setOwner",
		value: function setOwner(owner) {
			var _this2 = this;

			(0, _akutils.assert)(function (a) {
				return a.not(_this2[_owner], "Owner already set");
			});

			this[_owner] = owner;
		}

		//------------------------------------------------------------------------------------------------------
		// Property class overrides - no need to call super
		//
		// These are mostly proxies to the owner property
		//------------------------------------------------------------------------------------------------------

		/**
  	Creates the object to be assigned to the shadow.$ property. Subclasses can override this method
  	to setup a chain of specialized accessors (`$()`). See {@link Access} for details on setting up
  	specialized accessors. This is an advanced feature and rarely required.
  		@return {Access} a property accessor instance.
  */

	}, {
		key: "create$",
		value: function create$(impl) {
			return new _IsolatedAccess2.default(impl);
		}

		/**
  	An isolated property returns owner's `dotPath()` value.
  		@return {string} path with each component joined by a `.`
  		@see https://lodash.com/docs/4.17.4#result
  */

	}, {
		key: "dotPath",
		value: function dotPath() {
			return this[_owner].dotPath();
		}

		/**
  	An isolated property returns owner's `isActive()` value.
  		@return {boolean}
  */

	}, {
		key: "isActive",
		value: function isActive() {
			return this[_owner] && this[_owner].isActive() && _get(Object.getPrototypeOf(IsolatedProperty.prototype), "isActive", this).call(this);
		}

		/**
  	Gets if property is an actual isolated property managed by the store.
  		@return {boolean}
  */

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

		/**
  	An isolated property is never a root.
  		@return {boolean} `false`
  */

	}, {
		key: "isRoot",
		value: function isRoot() {
			return false;
		}

		/**
  	An isolated property returns owner property for the parent.
  		@return {[]}
  */

	}, {
		key: "parent",
		value: function parent() {
			return this[_owner];
		}

		//------------------------------------------------------------------------------------------------------
		// Property class overrides - the tricky ones
		//
		// Developer Note: Use great caution when overriding these methods as not their original intent
		//------------------------------------------------------------------------------------------------------

		/**
  	An isolated property returns owner's `isReadonly()` value.
  		@return {boolean}
  */

	}, {
		key: "isReadonly",
		value: function isReadonly() {
			var explicit = this.readonlyExplicit();
			var readonly = explicit !== undefined ? explicit : this.stateType()._readonly;

			// use readonly flag if explicitly set otherwise use value from owner
			return readonly === undefined ? this[_owner].isReadonly() : readonly;
		}
	}], [{
		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 createPropertyClass(shadowType, initialState, typeCallback, IsolatedProperty);
		}

		/**
  	Factory function for setting up the {@link StateType} `type` class variable with an appropriately
  	configured intial state.
  		Example usage:
  	```
         export default class SomeProperty extends MapProperty {
  		// implement property here
         }
          class SomeShadow extends MapShadow {
  		// implement shadow api here
         }
          IsolatedProperty.defineType(SomeProperty, SomeShadow, type => {
  		// configure type variable
         });
  	```
  		@param {MapProperty} PropClass - MapProperty subclass
  	@param {Object|MapShadow} [ShadowType] - `MapShadow` 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(IsolatedProperty.isPrototypeOf(PropClass), "PropClass must subclass IsolatedProperty");
			});

			_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 IsolatedProperty;
}(_Property3.default);

exports.default = IsolatedProperty;


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