"use strict";
// Derived from shared/hashing.js (optimizely/optimizely repo)
var murmur3 = require('murmurhash').v3;
/**
 * Static seeds used to generate different types of "random" hashes.
 * Changing these WILL change existing bucketing decisions!
 *
 * @enum {number}
 */
var HashSeed = {
    IGNORING: 0,
    BUCKETING: 1,
    FALLBACK: 2,
    HOLDBACK: 3,
    BEHAVIOR_EVENT: 0xa1eea1ee,
};
/**
 * Maximum number returned by murmur3
 * @type {number}
 * @const
 * @private
 */
var MAX_HASH_VALUE = Math.pow(2, 32);
/**
 * Returns an integer in [0, maxInt), representing the hash of data with the current seed
 * @param {string} data
 * @param {number} seed Seed for murmur3.
 * @param {number} maxInt Maximum integer.
 * @return {number} Integer in range [0, maxInt).
 */
var hashToInt = function (data, seed, maxInt) {
    return Math.floor(hashToReal(data, seed) * maxInt);
};
/**
 * Returns hashed value as a hex string.
 * @param {string} data A byte string to run murmur on. A byte string has no characters with a
 *   code point > 255. When in doubt pass ASCII or pass the string through optly.hashing.toByteString.
 * @param {number} seed The seed to use for murmur.
 * @return {string} Hashed value as a hexadecimal string.
 */
var hashToHex = function (data, seed) {
    var h1 = murmur3(data, seed);
    return (h1 >>> 16).toString(16) + (h1 & 0x0000ffff).toString(16);
};
/**
 * Returns a hash value in [0, 1.0) using murmur3.
 * @param {string} data A byte string to run murmur on. A byte string has no characters with a
 *   code point > 255. When in doubt pass ASCII or pass the string through toByteString.
 * @param {number} seed The seed to use for murmur.
 * @returns {number} A hash value in [0, 1).
 */
var hashToReal = function (data, seed) {
    var h1 = murmur3(data, seed);
    return (h1 >>> 0) / MAX_HASH_VALUE;
};
/**
 * Returns a byte string version of the given string. Any characters with a code point of less than 255
 * will be converted into a single byte/character. All other characters will be converted into two or
 * three bytes/characters.
 * @param {string} string A string to convert to a byte string.
 * @return {string} A hexadecimal string.
 */
var toByteString = function (string) {
    var fromCharCode = String.fromCharCode;
    // Unicode comprises 1,114,112 code points in the range 0 to 0x10FFFF.
    return string.replace(/[\S\s]/gi, function (c) {
        c = c.charCodeAt(0);
        var ret = fromCharCode(c & 0xff);
        if (c > 0xff) {
            ret = fromCharCode((c >>> 8) & 0xff) + ret;
        }
        if (c > 0xffff) {
            ret = fromCharCode(c >>> 16) + ret;
        }
        return ret;
    });
};
module.exports = {
    Seed: HashSeed,
    hashToHex: hashToHex,
    hashToInt: hashToInt,
    hashToReal: hashToReal,
    toByteString: toByteString,
};
