const HanyuuOAuth2LoadingIcon = function() {
    const element = <div class="oauth2-loading-icon"/>;
    for(let i = 0; i < 9; ++i)
        element.appendChild(<div class="oauth2-loading-icon-block"/>);

    // this is moderately cursed but it'll do
    const blocks = [
        element.children[3],
        element.children[0],
        element.children[1],
        element.children[2],
        element.children[5],
        element.children[8],
        element.children[7],
        element.children[6],
    ];

    let tsLastUpdate;
    let counter = 0;
    let playing = false;

    const update = tsCurrent => {
        try {
            if(tsLastUpdate !== undefined && (tsCurrent - tsLastUpdate) < 50)
                return;
            tsLastUpdate = tsCurrent;

            for(let i = 0; i < blocks.length; ++i)
                blocks[(counter + i) % blocks.length].classList.toggle('oauth2-loading-icon-block-hidden', i < 3);

            ++counter;
        } finally {
            if(playing)
                requestAnimationFrame(update);
        }
    };

    const play = () => {
        if(playing)
            return;
        playing = true;
        requestAnimationFrame(update);
    };
    const pause = () => { playing = false; };
    const stop = () => { pause(); counter = 0; };
    const restart = () => { stop(); play(); };

    return {
        get element() { return element; },
        get playing() { return playing; },

        play: play,
        pause: pause,
        stop: stop,
        restart: restart,
    };
};

const HanyuuOAuth2Loading = function(element) {
    if(typeof element === 'string')
        element = document.querySelector(element);
    if(!(element instanceof HTMLElement))
        element = <div class="oauth2-loading"/>;

    if(!element.classList.contains('oauth2-loading'))
        element.classList.add('oauth2-loading');

    let icon;
    if(element.childElementCount < 1) {
        icon = new HanyuuOAuth2LoadingIcon;
        icon.play();
        element.appendChild(<div class="oauth2-loading-frame">{icon}</div>);
    }

    return {
        get element() { return element; },

        get hasIcon() { return icon !== undefined; },
        get icon() { return icon; },

        get visible() { return !element.classList.contains('hidden'); },
        set visible(state) { element.classList.toggle('hidden', !state); },
    };
};
