

class Christmas {
    static init(root, hatSelectors, attributesForRng, exclusionSelectors,disableSnow) {
        this.root = root;
        this.hatSelectors = hatSelectors;
        this.attributesForRng = attributesForRng;
        this.exclusionSelectors = exclusionSelectors;
        this.disableSnow=disableSnow;
        document.addEventListener("DOMContentLoaded", () => {
            if (this.isChristmas() || window.location.hash == "#test-christmas25550") {
                this.loadNow();
            }
        });
    }
    static hashCode(v) {
        let hash = 0;
        for (var i = 0; i < v.length; i++) {
            var character = v.charCodeAt(i);
            hash = ((hash << 5) - hash) + character;
            hash = hash & hash; // Convert to 32bit integer
        }
        return hash;
    }
    static randomSeedParkMiller(seed) { // doesn't repeat b4 JS dies.
        // https://gist.github.com/blixt/f17b47c62508be59987b
        seed = seed % 2147483647
        seed = seed * 16807 % 2147483647
        return (seed - 1) / 2147483646

    }
    static loadNow() {
        if(!this.disableSnow)this.loadSnow();
        const hatLoadInt = () => {
            this.loadHats(this.hatSelectors, this.attributesForRng, this.exclusionSelectors);
        };
        setInterval(function () {
            hatLoadInt();
        }, 2000);
        hatLoadInt();

    }

    static isChristmas() {
        const date = new Date();
        if ((date.getMonth() + 1) != 12) return false;
        if (date.getDate() < 6) return false;
        return true;
    }

    static loadSnow() {
        console.log("Load snow...");
        const snowScript = document.createElement("script");
        snowScript.src = this.root + "snow.js"
        document.head.appendChild(snowScript);
        snowScript.onload = function () {
            console.log("Snow Loaded. Starting...");
            snow.start({
                "stickingRatio": 0.7,
                "wind": 3,
                "flakeCount": 32,
                "maxRadius": 1.9,
                "maxSpeed": 2,
                "minSpeed": 0.4
            });
        }
    }
    static getHats() {
        return [
            this.root + 'hats/hat1.png'
        ];
    }
    static loadHats(selectors, attributesForRng, exclusionSelectors) {

        const hats = this.getHats();

        selectors.forEach(selector => {
            document.querySelectorAll(selector).forEach(avatar => {
                if (avatar.hasAttribute("christmas25550-hasHat")) return;

                if (exclusionSelectors) {
                    for (let i = 0; i < exclusionSelectors.length; i++) {
                        const exclusionSelector = exclusionSelectors[i];
                        if (avatar.matches(exclusionSelector)) {
                            return;
                        }
                    }
                }

                let hueRotation = 0;
                if (attributesForRng && attributesForRng.length > 0) {
                    let seed = "";
                    for (let i = 0; i < attributesForRng.length; i++) {
                        const r = attributesForRng[i];
                        if (r.type == "attribute") {
                            if (avatar.hasAttribute(r.value)) {
                                seed = avatar.getAttribute(r.value);
                                console.log("Use attribute", r.value, "as seed");
                                if (r.transform) {
                                    seed = r.transform(seed);
                                    console.log("Transformed to ", seed);
                                }
                                break;
                            }
                        } else if (r.type == "text") {
                            seed = avatar.innerText;
                            console.log("Use innerText as seed");
                            if (r.transform) {
                                seed = r.transform(seed);
                                console.log("Transformed to ", seed);
                            }
                            break;
                        }
                    }

                    seed = seed.trim();
                    const seedHashCode = this.hashCode(seed);
                    if (seed != "") {
                        hueRotation = this.randomSeedParkMiller(seedHashCode);
                    }
                }

                const parent = avatar.parentNode;
                const avatarBound = avatar.getBoundingClientRect();
                if (avatarBound.width == 0 || avatarBound.height == 0) return;
                const parentBound = parent.getBoundingClientRect();

                const parentPosMode = window.getComputedStyle(parent).position;
                if (parentPosMode != "absolute" && parentPosMode != "fixed" && parentPosMode != "relative") parent.style.position = "relative";


                console.log("Add hat to", avatar);

                const hat = document.createElement("div");
                hat.classList.add("christmas25550-hat");

                const hatImg = hats[Math.floor(Math.random() * hats.length)];
                hat.style.pointerEvents = "none";
                hat.style.backgroundImage = "url('" + hatImg + "')";
                hat.style.backgroundPosition = "left bottom";
                hat.style.filter = "hue-rotate(" + hueRotation + "turn)";
                hat.style.backgroundRepeat = "no-repeat";
                hat.style.backgroundSize = "contain";
                hat.style.display = "block";
                hat.style.position = "absolute";
                const avatarWidth = Math.min(avatarBound.width, 124);
                const avatarHeight = Math.min(avatarBound.height, 124);
                hat.style.width = avatarWidth + "px";
                hat.style.height = avatarHeight + "px";
                hat.style.zIndex = "140";

                hat.style.left = (parentBound.left - avatarBound.left - Math.min(avatarHeight, avatarWidth) * 0.3) + "px";
                // hat.style.left = (avatarBound.left - parentBound.left - avatarBound.width * 0.3) + "px";
                hat.style.top = (avatarBound.top - parentBound.top - avatarHeight * 0.76) + "px";

                parent.appendChild(hat);
                avatar.setAttribute("christmas25550-hasHat", "true");


            });
        });
    }
}
