'use strict'; var clear = require('es5-ext/array/#/clear') , assign = require('es5-ext/object/assign') , callable = require('es5-ext/object/valid-callable') , value = require('es5-ext/object/valid-value') , d = require('d') , autoBind = require('d/auto-bind') , Symbol = require('es6-symbol') , defineProperty = Object.defineProperty , defineProperties = Object.defineProperties , Iterator; module.exports = Iterator = function (list, context) { if (!(this instanceof Iterator)) return new Iterator(list, context); defineProperties(this, { __list__: d('w', value(list)), __context__: d('w', context), __nextIndex__: d('w', 0) }); if (!context) return; callable(context.on); context.on('_add', this._onAdd); context.on('_delete', this._onDelete); context.on('_clear', this._onClear); }; defineProperties(Iterator.prototype, assign({ constructor: d(Iterator), _next: d(function () { var i; if (!this.__list__) return; if (this.__redo__) { i = this.__redo__.shift(); if (i !== undefined) return i; } if (this.__nextIndex__ < this.__list__.length) return this.__nextIndex__++; this._unBind(); }), next: d(function () { return this._createResult(this._next()); }), _createResult: d(function (i) { if (i === undefined) return { done: true, value: undefined }; return { done: false, value: this._resolve(i) }; }), _resolve: d(function (i) { return this.__list__[i]; }), _unBind: d(function () { this.__list__ = null; delete this.__redo__; if (!this.__context__) return; this.__context__.off('_add', this._onAdd); this.__context__.off('_delete', this._onDelete); this.__context__.off('_clear', this._onClear); this.__context__ = null; }), toString: d(function () { return '[object Iterator]'; }) }, autoBind({ _onAdd: d(function (index) { if (index >= this.__nextIndex__) return; ++this.__nextIndex__; if (!this.__redo__) { defineProperty(this, '__redo__', d('c', [index])); return; } this.__redo__.forEach(function (redo, i) { if (redo >= index) this.__redo__[i] = ++redo; }, this); this.__redo__.push(index); }), _onDelete: d(function (index) { var i; if (index >= this.__nextIndex__) return; --this.__nextIndex__; if (!this.__redo__) return; i = this.__redo__.indexOf(index); if (i !== -1) this.__redo__.splice(i, 1); this.__redo__.forEach(function (redo, i) { if (redo > index) this.__redo__[i] = --redo; }, this); }), _onClear: d(function () { if (this.__redo__) clear.call(this.__redo__); this.__nextIndex__ = 0; }) }))); defineProperty(Iterator.prototype, Symbol.iterator, d(function () { return this; })); defineProperty(Iterator.prototype, Symbol.toStringTag, d('', 'Iterator'));