(function (app) {
    'use strict';

    const u = app.modules.util;

    function makeArray(schema, ui, path, value, options) {
        const wrap = u.h('div', { className: 'form-field form-array' });
        const label = (ui && ui['ui:title']) || schema.title || options.fieldName || '';
        if (label) {
            const lbl = u.h('label', { className: 'form-field__label' });
            lbl.appendChild(document.createTextNode(label));
            if (options.required) {
                lbl.appendChild(u.h('span', { className: 'required-mark' }, '*'));
            }
            wrap.appendChild(lbl);
        }
        if (schema.description) {
            wrap.appendChild(u.h('div', { className: 'form-field__description' }, schema.description));
        }
        const errEl = u.h('div', { className: 'form-field__error', hidden: true });
        wrap.appendChild(errEl);

        const rowsEl = u.h('div', { className: 'form-array__rows' });
        wrap.appendChild(rowsEl);

        const itemSchema = schema.items || { type: 'string' };
        const itemUi = (ui && ui.items) || {};
        const uiOpts = (ui && ui['ui:options']) || {};
        const addable = uiOpts.addable !== false;
        const removable = uiOpts.removable !== false;

        const rows = [];

        function repath() {
            for (let i = 0; i < rows.length; i++) {
                rows[i].widget.path = u.ptrPush(path, String(i));
            }
        }

        function addRow(rowValue) {
            const idx = rows.length;
            const rowPath = u.ptrPush(path, String(idx));
            const childWidget = app.modules.render.create(itemSchema, itemUi, rowPath, rowValue, {
                fieldName: '',
                required: false
            });

            const rowEl = u.h('div', { className: 'form-array__row' });
            const body = u.h('div', { className: 'form-array__row-body' });
            body.appendChild(childWidget.el);
            rowEl.appendChild(body);

            if (removable) {
                const actions = u.h('div', { className: 'form-array__row-actions' });
                const removeBtn = u.h('button', {
                    type: 'button',
                    className: 'btn btn-sm btn-secondary',
                    title: 'Remove this row',
                    onClick: function () { removeRow(rowEl); }
                }, '×');
                actions.appendChild(removeBtn);
                rowEl.appendChild(actions);
            }

            rows.push({ widget: childWidget, rowEl: rowEl });
            rowsEl.appendChild(rowEl);
        }

        function removeRow(targetEl) {
            for (let i = 0; i < rows.length; i++) {
                if (rows[i].rowEl === targetEl) {
                    rows.splice(i, 1);
                    targetEl.remove();
                    repath();
                    return;
                }
            }
        }

        const initial = Array.isArray(value) ? value : [];
        for (let i = 0; i < initial.length; i++) {
            addRow(initial[i]);
        }

        if (addable) {
            const addBtn = u.h('button', {
                type: 'button',
                className: 'btn btn-sm btn-secondary form-array__add',
                onClick: function () { addRow(undefined); }
            }, '+ Add');
            wrap.appendChild(addBtn);
        }

        return {
            el: wrap,
            path: path,
            type: 'array',
            read: function () {
                const out = [];
                for (let i = 0; i < rows.length; i++) {
                    const v = rows[i].widget.read();
                    if (v !== undefined) {
                        out.push(v);
                    }
                }
                return out;
            },
            setError: function (msg) {
                errEl.textContent = msg;
                errEl.hidden = false;
            },
            clearErrors: function () {
                errEl.textContent = '';
                errEl.hidden = true;
                for (let i = 0; i < rows.length; i++) {
                    rows[i].widget.clearErrors();
                }
            },
            child: function (idxStr) {
                const i = parseInt(idxStr, 10);
                return (rows[i] && rows[i].widget) || null;
            }
        };
    }

    app.modules.array = { makeArray: makeArray };
})(window.formApp);
