const MakaiASCII = () => {
    const chars = $queryAll('.js-ascii-char');
    const search = $query('.js-ascii-search');

    const charsFilter = (filter) => {
        if(!filter) {
            for(const chr of chars)
                chr.classList.remove('hidden');
            return;
        }

        filter = filter.toLowerCase();

        for(const chr of chars) {
            const code = (chr.dataset.keyCode || 0).toString().toLowerCase();
            const print = (chr.dataset.keyPrint || "\0").toString().toLowerCase();
            const desc = (chr.dataset.keyDesc || '').toString().toLowerCase();
            const html = (chr.dataset.keyHtml || "\0").toString().toLowerCase();
            const codeInt = parseInt(code);
            const isMatch = (filter === 'printable' && (codeInt > 31 && codeInt < 127))
                    || (filter === 'control' && (codeInt < 32 || codeInt === 127))
                    || code == filter || print == filter
                    || html == filter || desc.indexOf(filter) >= 0;
            chr.classList.toggle('hidden', !isMatch);
        }
    };

    search.addEventListener('keyup', () => {
        location.hash = search.value.trim();
    });
    window.addEventListener('hashchange', () => {
        const filter = decodeURIComponent((location.hash || '#').substring(1));
        search.value = filter;
        charsFilter(filter);
    });
    if(location.hash.length > 0) {
        search.value = location.hash.substring(1).trim();
        charsFilter(search.value);
    }

    for(const chr of chars) {
        chr.addEventListener('click', ev => {
            let target = ev.target;
            while(target !== null && typeof target.dataset.copy === 'undefined') {
                target = target.parentNode || null;

                if(target.classList.contains('char'))
                    break;
            }

            if(target === null || typeof target.dataset.copy === 'undefined')
                return;

            const doCopy = () => { navigator.clipboard.writeText(target.dataset.copy); };

            if(typeof window.mozInnerScreenX !== 'undefined')
                doCopy();
            else
                navigator.permissions.query({ name: 'clipboard-write' }).then(res => {
                    if(res.state === 'granted' || res.state === 'prompt')
                        doCopy();
                });
        });
    }
};