/**

* Refer to https://cp-algorithms.com/string/string-hashing.html
* @param {string} str
* @param {number} p It is reasonable to make p a prime number roughly equal to 
* the number of characters in the input alphabet. Maybe 257 is a good choice.
* @param {number} m Obviously m should be a large number, since the probability
* of two random strings colliding is about 1/m. A good choice for m is some 
* large prime number, for example, 1e9+9 (1000000007 and 1000000009 are the 
* largest known pair of twin primes of the form [10^n + 7, 10^n + 9]. Refer to 
* https://primes.utm.edu/curios/page.php/1000000009.html)
*/

function polynomial_rolling_hash(str, p, m) {

let h = 0;
let pow = 1;
for (let i = 0; i < str.length; i++) {
    const c = str.charCodeAt(i);
    // h = (h + (c - 'a'.charCodeAt(0) + 1) * pow) % m;
    h = (h + c * pow) % m;
    pow = (pow * p) % m;
}
return h;

}

function invertColor(hex, bw) {

if (hex.indexOf('#') === 0) {
    hex = hex.slice(1);
}
// convert 3-digit hex to 6-digits.
if (hex.length === 3) {
    hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
}
if (hex.length !== 6) {
    throw new Error('Invalid HEX color.');
}
var r = parseInt(hex.slice(0, 2), 16),
    g = parseInt(hex.slice(2, 4), 16),
    b = parseInt(hex.slice(4, 6), 16);
if (bw) {
    // http://stackoverflow.com/a/3943023/112731
    return (r * 0.299 + g * 0.587 + b * 0.114) > 186
        ? '#000000'
        : '#FFFFFF';
}
// invert color components
r = (255 - r).toString(16);
g = (255 - g).toString(16);
b = (255 - b).toString(16);
// pad each with zeros and return
return "#" + padZero(r) + padZero(g) + padZero(b);

}

function padZero(str, len) {

len = len || 2;
var zeros = new Array(len).join('0');
return (zeros + str).slice(-len);

}

function hashColor(str) {

const p = 257;
const m = 1e9+9;
color = (polynomial_rolling_hash(str, p, m) % 16777215).toString(16);
return '#' + padZero(color, 6);

}

function setInvertedColor(className) {

let elems = document.getElementsByClassName(className);
for (const elem of elems) {
    const bgColor = hashColor(elem.innerText);
    const color = invertColor(bgColor, true);
    elem.style['color'] = color;
    elem.style['background-color'] = bgColor;
}

}