import { UUID_REGEXP } from '@ibgib/helper-gib/dist/constants.mjs';
import { getRegExp, } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
import { GLOBAL_LOG_A_LOT, SAFE_SPECIAL_CHARS } from '../../core-constants.mjs';
const logalot = GLOBAL_LOG_A_LOT || false;
/**
 * Fluent-style builder helper class.
 *
 * I'm making this to share common fields' settings among witness classes.
 *
 * Descend from this class for sharing other commonalities.
 */
export class DynamicFormBuilder {
    lc = `[${DynamicFormBuilder.name}]`;
    items = [];
    what = '';
    /**
     * pool of uuids pre-calculated to be passed in to the builder. if this is
     * falsy, then it will use a Math.random() based approach.
     */
    idPool = [];
    /**
     * hacky wrapper for this.idPool.pop()
     */
    getNewId() {
        const lc = `${this.lc}[${this.getNewId.name}]`;
        if (this.idPool?.length > 0) {
            return this.idPool.pop() ?? '';
        }
        else {
            // weak implementation...
            let resultArray = [];
            const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
            const charLength = chars.length;
            for (let i = 0; i < 32; i++) {
                let charIndex = Math.floor(Math.random() * charLength);
                resultArray.push(chars[charIndex]);
            }
            let id = resultArray.join('');
            if (logalot) {
                console.log(`${lc} id: ${id} (I: c6591ffee6d5bbea79ed19cfa6630422)`);
            }
            return id;
        }
    }
    /**
     * Start fluent calls with this.
     */
    forA({ what, }) {
        this.what = what || 'thingy';
        return this;
    }
    addItem(item) {
        if (!item.uuid) {
            item.uuid = this.getNewId();
        }
        this.items.push(item);
    }
    /**
     * Empty function simply for more natural looking fluent syntax.
     *
     * You can override this for custom form builders that descend from this
     * class.
     *
     * @returns this
     */
    with({ idPool, }) {
        if (idPool) {
            this.idPool = idPool;
        }
        return this;
    }
    /**
     * I'm not a great fluent builder writer for TypeScript,
     * and this function acts as a caster for which members of
     * which concrete classes to expose for the proceeding builder lines.
     *
     *
     * Basically, you use this to typecast the builder, possibly redundantly since
     * I don't have any ordering implemented atow.
     *
     * @returns typecasted fluent builder
     */
    and() { return this; }
    name({ of: value, required = true, defaultValue, }) {
        this.addItem({
            // witness.data.name
            name: "name",
            description: `What to call this ${this.what}. Doesn't have to be unique, no spaces, up to 32 alphanumerics/underscores in length.`,
            label: "Name",
            placeholder: `e.g. "bob_the_cool"`,
            regexp: getRegExp({ min: 1, max: 32, noSpaces: true }),
            regexpErrorMsg: '1 to 32 characters, no spaces, underscores allowed.',
            required,
            dataType: 'text',
            value,
            defaultValue,
        });
        return this;
    }
    description({ of: value, required, defaultValue, }) {
        this.addItem({
            // witness.data.description
            name: "description",
            description: `Description/notes for this ${this.what}.`,
            label: "Description",
            placeholder: `Describe these ${this.what} settings here...`,
            regexp: getRegExp({ min: 0, max: 155, chars: SAFE_SPECIAL_CHARS }),
            regexpErrorMsg: `0 to 155 alphanumerics or any of ${SAFE_SPECIAL_CHARS}`,
            // regexpSource: getRegExp({min: 0, max: 155, chars: SAFE_SPECIAL_CHARS}).source,
            dataType: 'textarea',
            required,
            value,
            defaultValue,
        });
        return this;
    }
    classname({ of, required = true, }) {
        this.addItem({
            // witness.data.classname
            name: "classname",
            description: `Technical setting that is the name of the ${this.what}'s class in computer code.`,
            label: "Classname",
            regexp: getRegExp({ min: 1, max: 128, noSpaces: true }),
            regexpErrorMsg: `1 to 128 alphanumerics or underscores without spaces`,
            // regexpSource: getRegExp({min: 1, max: 128, noSpaces: true}).source,
            dataType: 'text',
            value: of,
            readonly: true,
            required,
        });
        return this;
    }
    uuid({ of, label, required, }) {
        this.addItem({
            // witness.data.uuid
            name: "uuid",
            description: `Unique(ish) id of the ${this.what}.`,
            label: label ?? "ID",
            dataType: 'text',
            value: of,
            regexp: UUID_REGEXP,
            regexpErrorMsg: '1 to 256 alphanumerics, underscores, dots, hyphens allowed.',
            readonly: true,
            required,
        });
        return this;
    }
    version({ of, required, }) {
        this.addItem({
            // witness.data.version
            name: "version",
            description: `Technical setting indicating the version of the ${this.what}.`,
            label: "Version",
            dataType: 'text',
            value: of || '',
            readonly: true,
            required,
        });
        return this;
    }
    /**
     * To pass in a completely customized item info.
     *
     * @returns `this` for fluent builder
     */
    customItem(item) {
        this.addItem(item);
        return this;
    }
    outputItems() {
        return this.items;
    }
    outputForm({ formName, label, }) {
        return {
            name: formName,
            // description: this.description ?? `This is a form for a ${this.what}`,
            description: `This is a form for a ${this.what}`,
            label: label ?? this.what,
            items: this.items,
        };
    }
}
//# sourceMappingURL=form-helper.mjs.map