/**
 * @file Parses a string argument and returns an integer of the specified radix.
 * @version 2.0.0
 * @author Xotic750 <Xotic750@gmail.com>
 * @copyright  Xotic750
 * @license {@link <https://opensource.org/licenses/MIT> MIT}
 * @module parse-int-x
 */

'use strict';

var nativeParseInt = parseInt;
var NAN = require('nan-x');
var toStr = require('to-string-x');
var trimLeft2016 = require('trim-left-x').trimLeft2016;
var trimLeft2018 = require('trim-left-x').trimLeft2018;
var chachedCtrs = require('cached-constructors-x');
var castNumber = chachedCtrs.Number;
var charAt = chachedCtrs.String.prototype.charAt;
var hexRegex = /^[-+]?0[xX]/;
var test = hexRegex.test;

var $parseInt2016 = function parseInt2016(string, radix) {
  var str = trimLeft2016(toStr(string));

  return nativeParseInt(str, castNumber(radix) || (test.call(hexRegex, str) ? 16 : 10));
};

var $parseInt2018 = function parseInt2018(string, radix) {
  var str = trimLeft2018(toStr(string));
  if (charAt.call(str, 0) === '\u180E') {
    return NAN;
  }

  return nativeParseInt(str, castNumber(radix) || (test.call(hexRegex, str) ? 16 : 10));
};

module.exports = {
  /**
   * Reference to parseInt2018.
   */
  parseInt: $parseInt2018,

  /**
   * This method parses a string argument and returns an integer of the specified
   * radix (the base in mathematical numeral systems). (ES2016)
   *
   * @param {string} string - The value to parse. If the string argument is not a
   *  string, then it is converted to a string (using the ToString abstract
   *  operation). Leading whitespace in the string argument is ignored.
   * @param {number} radix - An integer between 2 and 36 that represents the radix
   *  (the base in mathematical numeral systems) of the above mentioned string.
   *  Specify 10 for the decimal numeral system commonly used by humans. Always
   *  specify this parameter to eliminate reader confusion and to guarantee
   *  predictable behavior. Different implementations produce different results
   *  when a radix is not specified, usually defaulting the value to 10.
   * @throws {TypeError} If target is a Symbol or is not coercible.
   * @returns {number} An integer number parsed from the given string. If the first
   *  character cannot be converted to a number, NaN is returned.
   * @example
   * var $parseInt = require('parse-int-x').parseInt2016;
   *
   * // The following examples all return 15
   * $parseInt(' 0xF', 16);
   * $parseInt(' F', 16);
   * $parseInt('17', 8);
   * $parseInt(021, 8);
   * $parseInt('015', 10);   // $parseInt(015, 10); will return 15
   * $parseInt(15.99, 10);
   * $parseInt('15,123', 10);
   * $parseInt('FXX123', 16);
   * $parseInt('1111', 2);
   * $parseInt('15 * 3', 10);
   * $parseInt('15e2', 10);
   * $parseInt('15px', 10);
   * $parseInt('12', 13);
   *
   * //The following examples all return NaN:
   * $parseInt('Hello', 8); // Not a number at all
   * $parseInt('546', 2);   // Digits are not valid for binary representations
   */
  parseInt2016: $parseInt2016,

  /**
   * This method parses a string argument and returns an integer of the specified
   * radix (the base in mathematical numeral systems). (ES2018)
   *
   * @param {string} string - The value to parse. If the string argument is not a
   *  string, then it is converted to a string (using the ToString abstract
   *  operation). Leading whitespace in the string argument is ignored.
   * @param {number} radix - An integer between 2 and 36 that represents the radix
   *  (the base in mathematical numeral systems) of the above mentioned string.
   *  Specify 10 for the decimal numeral system commonly used by humans. Always
   *  specify this parameter to eliminate reader confusion and to guarantee
   *  predictable behavior. Different implementations produce different results
   *  when a radix is not specified, usually defaulting the value to 10.
   * @throws {TypeError} If target is a Symbol or is not coercible.
   * @returns {number} An integer number parsed from the given string. If the first
   *  character cannot be converted to a number, NaN is returned.
   * @example
   * var $parseInt = require('parse-int-x').parseInt2018;
   *
   * // The following examples all return 15
   * $parseInt(' 0xF', 16);
   * $parseInt(' F', 16);
   * $parseInt('17', 8);
   * $parseInt(021, 8);
   * $parseInt('015', 10);   // $parseInt(015, 10); will return 15
   * $parseInt(15.99, 10);
   * $parseInt('15,123', 10);
   * $parseInt('FXX123', 16);
   * $parseInt('1111', 2);
   * $parseInt('15 * 3', 10);
   * $parseInt('15e2', 10);
   * $parseInt('15px', 10);
   * $parseInt('12', 13);
   *
   * //The following examples all return NaN:
   * $parseInt('Hello', 8); // Not a number at all
   * $parseInt('546', 2);   // Digits are not valid for binary representations
   */
  parseInt2018: $parseInt2018
};
