"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 _ArrayShadow = require("./ArrayShadow");

var _ArrayShadow2 = _interopRequireDefault(_ArrayShadow);

var _IndexedApi = require("./IndexedApi");

var _IndexedApi2 = _interopRequireDefault(_IndexedApi);

var _IndexedShadowImpl = require("./IndexedShadowImpl");

var _IndexedShadowImpl2 = _interopRequireDefault(_IndexedShadowImpl);

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

var _Property3 = _interopRequireDefault(_Property2);

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

var _MapProperty2 = _interopRequireDefault(_MapProperty);

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

/**
	`ArrayProperty` models an [Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)
	and the shadow API exposes all `Array` methods, such as `filter()`, `push()`, `pop()`,
	and `reduce()` to name a few. The {@link ArrayShadow} allows for random access and assignment, such as
	`todos[1].desc`.

	The default shadow class is {@link ArrayShadow}.

	Use `ArrayProperty` when you want to model an array state property and allow for the use of `Array` mutation methods.
	You can then specify a custom shadow api to extend the `ArrayShadow` api.

	The `_indexed` instance variable exposes a {@link IndexedApi} instance for working with properties.
	Use `this._indexed` to perform `array` mutations, such as `pop()`, `push()`, `shift()`, and `splice()`.
	For example,

	```js
	this._indexed.push("new element");
	```
	would append "new element" to the array.

	@see {@link ArrayShadow}
*/

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

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

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

		_this._indexed = new _IndexedApi2.default(_this);

		_this.setImplementationClass(_IndexedShadowImpl2.default);
		_this.setShadowClass(_ArrayShadow2.default);
		return _this;
	}

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


	_createClass(ArrayProperty, 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, ArrayProperty, _ArrayShadow2.default);
		}

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

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

	return ArrayProperty;
}(_Property3.default);

exports.default = ArrayProperty;


_StateType2.default.defineType(ArrayProperty, function (spec) {
	spec.initialState([]).elementType(_MapProperty2.default.type).typeName("ArrayProperty");
});