/**
 * @file Determine whether the passed value is a zero based index.
 * @version 1.1.0
 * @author Xotic750 <Xotic750@gmail.com>
 * @copyright  Xotic750
 * @license {@link <https://opensource.org/licenses/MIT> MIT}
 * @module is-index-x
 */

'use strict';

var safeToString = require('to-string-symbols-supported-x');
var toInteger = require('to-integer-x').toInteger2018;
var toNumber = require('to-number-x').toNumber2018;
var mathClamp = require('math-clamp-x');
var MAX_SAFE_INTEGER = require('max-safe-integer');
var reIsUint = /^(?:0|[1-9]\d*)$/;
var rxTest = reIsUint.test;

/**
 * This method determines whether the passed value is a zero based index.
 * JavaScript arrays are zero-indexed: the first element of an array is at
 * index 0, and the last element is at the index equal to the value of the
 * array's length property minus 1.
 *
 * @param {number|string} value - The value to be tested for being a zero based index.
 * @param {number} [length=MAX_SAFE_INTEGER] - The length that sets the upper bound.
 * @returns {boolean} A Boolean indicating whether or not the given value is a
 * zero based index within bounds.
 * @example
 * var isIndex = require('is-index-x');
 *
 * isIndex(0);                    // true
 * isIndex(1);                    // true
 * isIndex('10');                 // true
 *
 * isIndex(-100000);              // false
 * isIndex(Math.pow(2, 53));      // false
 * isIndex(0.1);                  // false
 * isIndex(Math.PI);              // false
 * isIndex(NaN);                  // false
 * isIndex(Infinity);             // false
 * isIndex(-Infinity);            // false
 * isIndex(true);                 // false
 * isIndex(false);                // false
 * isIndex([1]);                  // false
 * isIndex(10, 10);               // false
 */
module.exports = function isIndex(value) {
  var string = safeToString(value);
  if (rxTest.call(reIsUint, string) === false) {
    return false;
  }

  var number = toNumber(string);
  if (arguments.length > 1) {
    return number < mathClamp(toInteger(arguments[1]), MAX_SAFE_INTEGER);
  }

  return number < MAX_SAFE_INTEGER;
};
