'use strict';
var _getIterator2 = require('babel-runtime/core-js/get-iterator');
var _getIterator3 = _interopRequireDefault(_getIterator2);
var _regenerator = require('babel-runtime/regenerator');
var _regenerator2 = _interopRequireDefault(_regenerator);
var _iterator = require('babel-runtime/core-js/symbol/iterator');
var _iterator2 = _interopRequireDefault(_iterator);
var _keys = require('babel-runtime/core-js/object/keys');
var _keys2 = _interopRequireDefault(_keys);
var _getRange = require('./utils/getRange');
var _zip = require('./utils/zip');
var _some = require('./utils/some');
var _every = require('./utils/every');
var _getReadableStream = require('./utils/getReadableStream');
var _indexOf = require('./utils/indexOf');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* @class Harray
* @classdesc An infinite array.
* @property {Infinity} length - Returns the length of the Harray. (TIP: It's infinite)
* @property {Array} cycle - If the harray uses a finite cycle to generate its elements, the cycle will be here, otherwise it will be undefined.<br>
* Please see the [Harray.cycle() method]{@link Harray.cycle}.
* @param {...Number | Array} element - Every number passed as argument before the formula will be used as an element. You can also pass an array as the first argument instead of multiple elements.
* @param {Harray~formula} formula - A formula which will be used to calculate the next element.<br>
* If it does not exist the difference between the last two elements will be used as increment value to generate the sequence.<br>
* If there's a single element and no formula was provided the sequence will be generated using 1 as increment.
* @example
* let evensHarray = new Harray(0, 2);
* evensHarray.get(2) // -> 4
* evensHarray.get(5) // -> 10
*
* let oddsHarray = new Harray(1, 3);
* oddsHarray.get(3) // -> 7
* oddsHarray.get(4) // -> 9
*
* let binaryHarray = new Harray(1, function(element) {
* return element * 2;
* };
*
* // If your environment supports Proxies you can access elements directly using brackets notation
* binaryHarray[1] // -> 2
* binaryHarray[2] // -> 4
* binaryHarray[3] // -> 8
*
* // Otherwise you can use `.get(x)`
* binaryHarray.get(1) // -> 2
* binaryHarray.get(2) // -> 4
* binaryHarray.get(3) // -> 8
*
* let nonUniformHarray = new Harray(1, 10, 22, 24);
* nonUniformHarray.get(1) // -> 10
* nonUniformHarray.get(3) // -> 24
* nonUniformHarray.get(4) // -> 26
* nonUniformHarray.get(5) // -> 28
*
* let oneItemHarray = new Harray(10);
* oneItemHarray.get(0) // -> 10
* oneItemHarray.get(1) // -> 11
* oneItemHarray.get(2) // -> 12
*
* let oneItemHarray = new Harray([20, 30]);
* oneItemHarray.get(0) // -> 20
* oneItemHarray.get(1) // -> 30
* oneItemHarray.get(2) // -> 40
*/
function Harray() {
var _this = this;
var args = arguments;
if (Object.prototype.toString.call(arguments[0]) === '[object Array]') {
args = arguments[0];
if (typeof arguments[1] === 'function') {
args.push(arguments[1]);
}
}
this.formula = function (el) {
return el + 1;
};
var formulaExists = false;
for (var i = 0; i < args.length; i++) {
if (typeof args[i] === 'function') {
this.formula = args[i];
formulaExists = true;
break;
} else {
this[i] = args[i];
}
}
if (args.length >= 2 && !formulaExists) {
this.formula = function (el) {
return el + args[args.length - 1] - args[args.length - 2];
};
}
if (Proxy !== undefined) {
return new Proxy(this, {
get: function get(target, index) {
return _this.get(index);
}
});
}
}
Harray.prototype.length = Infinity;
/**
* This is the formula that will be used to generate the next element in the sequence.
* It receives the current element, does whatever you want with it and then returns the next element for the sequence.
* @callback Harray~formula
* @param {*} element - The element before the one being calculated now.
* @param {Number} index - The index for the element being calculated now.
* @returns nextElement - The next element for the sequence.
* @example
* let timesTen = function(element) {
* return element * 10;
* }
*
* let harr = new Harray(2, timesTen);
* harr.get(0) // -> 2
* harr.get(1) // -> 20
* harr.get(2) // -> 200
*
* let twoTimesIndex = function(element, index) {
* return index * 2;
* }
*
* let anotherHarr = new Harray(0, twoTimesIndex);
* harr.get(0) // -> 0
* harr.get(1) // -> 2
* harr.get(2) // -> 4
*
*/
/**
* Gets the value from an index.
* If your environment supports proxies you can directly access values using brackets notation, just like: `myHarray[1]`.
* @method
* @name Harray#get
* @param {Number} index - A value's index.
* @returns value - The value of an index.
*/
Harray.prototype.get = function get(index) {
if (this[index] !== undefined) {
return this[index];
} else {
var lastKey = (0, _keys2.default)(this).length - 2;
var result = this[lastKey];
for (var i = lastKey; i < index; i++) {
result = this.formula(result, i + 1);
this[i + 1] = result;
}
return this[index] = result;
}
};
/**
* Sets the value for an index.
* @method
* @name Harray#set
* @param {Number} index - An index.
* @param {*} index - The value for that index.
* @returns harray - The Harray instance in which the value has been set.
*/
Harray.prototype.set = function set(index, value) {
this[index] = value;
return this;
};
/**
* Defines an iterator for Harray.
* @method
* @returns GeneratorFunctionPrototype
*/
Harray.prototype[_iterator2.default] = _regenerator2.default.mark(function _callee() {
var index, reset;
return _regenerator2.default.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
index = 0;
case 1:
if (!true) {
_context.next = 8;
break;
}
_context.next = 4;
return this.get(index++);
case 4:
reset = _context.sent;
if (reset) {
index = 0;
}
_context.next = 1;
break;
case 8:
case 'end':
return _context.stop();
}
}
}, _callee, this);
});
/** Gets the Harray iterator.
* @name Harray#getIterator
* @method
* @returns GeneratorFunctionPrototype
*/
Harray.prototype.getIterator = _regenerator2.default.mark(function _callee2() {
return _regenerator2.default.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
return _context2.delegateYield((0, _getIterator3.default)(this), 't0', 1);
case 1:
case 'end':
return _context2.stop();
}
}
}, _callee2, this);
});
/**
* Creates a Harray object which repeats the given cycle.
* @method
* @name Harray.cycle
* @param {...*|Array} cycle - Arguments you want to use to create a cycle or an array of elements.
* @returns Harray - A Harray object which repeats the given cycle.
* @example
* let cycle = Harray.cycle(1, 2, 3);
*
* cycle.get(2) // -> 3
* cycle.get(3) // -> 1
* cycle.get(4) // -> 2
*
* let anotherCycle = Harray.cycle([0, 1]);
* anotherCycle.get(1) // -> 1
* anotherCycle.get(2) // -> 0
*/
Harray.cycle = function cycle(cycleElements) {
var h = new Harray();
h.cycle = arguments.length > 1 ? Array.prototype.slice.call(arguments) : cycleElements;
h.get = function (index) {
if (this[index] !== undefined) {
return this[index];
} else {
var result = this.cycle[index % this.cycle.length];
this[index] = result;
return result;
}
};
return h;
};
/**
* Adds a method to the Harray prototype.
* @method
* @name Harray.addMethod
* @param {String} methodName - The name of the property which will hold the method.
* @param {Function} method - The method which will be added to the prototype.
* @example
* let getDoubleFunction = function(index) {
* return this.get(i) * 2;
* }
*
* Harray.addMethod('getDouble', getDoubleFunction);
*
* let harr = new Harray(1, 2);
* harr.getDouble(0) // -> 2
* harr.getDouble(1) // -> 4
*/
Harray.addMethod = function addMethod(methodName, method) {
Harray.prototype[methodName] = method;
};
Harray.addMethod('getRange', _getRange.getRange);
Harray.addMethod('zip', _zip.zip);
Harray.addMethod('some', _some.some);
Harray.addMethod('every', _every.every);
Harray.addMethod('getReadableStream', _getReadableStream.getReadableStream);
Harray.addMethod('indexOf', _indexOf.indexOf);
module.exports = Harray;