(function (app) {
    'use strict';

    const util = {};

    util.h = function (tag, attrs) {
        const el = document.createElement(tag);
        if (attrs) {
            for (const k of Object.keys(attrs)) {
                const v = attrs[k];
                if (v == null || v === false) {
                    continue;
                }
                if (k === 'className') {
                    el.className = v;
                } else if (k.length > 2 && k.slice(0, 2) === 'on' && typeof v === 'function') {
                    el.addEventListener(k.slice(2).toLowerCase(), v);
                } else if (v === true) {
                    el.setAttribute(k, '');
                } else {
                    el.setAttribute(k, v);
                }
            }
        }
        for (let i = 2; i < arguments.length; i++) {
            const c = arguments[i];
            if (c == null || c === false) {
                continue;
            }
            if (typeof c === 'string' || typeof c === 'number') {
                el.appendChild(document.createTextNode(String(c)));
            } else {
                el.appendChild(c);
            }
        }
        return el;
    };

    // JSON Pointer (RFC 6901): encode one segment.
    util.ptrEnc = function (s) {
        return String(s).replace(/~/g, '~0').replace(/\//g, '~1');
    };

    util.ptrPush = function (path, segment) {
        return path + '/' + util.ptrEnc(segment);
    };

    util.ptrParse = function (path) {
        if (!path) {
            return [];
        }
        return path.split('/').slice(1).map(function (s) {
            return s.replace(/~1/g, '/').replace(/~0/g, '~');
        });
    };

    let idCounter = 0;
    util.uid = function (prefix) {
        idCounter += 1;
        return (prefix || 'f') + '-' + idCounter;
    };

    // Turn camelCase / snake_case into a Title Case string for default labels.
    util.humanize = function (name) {
        return String(name)
            .replace(/_/g, ' ')
            .replace(/([a-z])([A-Z])/g, '$1 $2')
            .replace(/^./, function (c) { return c.toUpperCase(); });
    };

    app.modules.util = util;
})(window.formApp);
