import { __decorate } from "tslib";
import { Actions, configReducer, coreReducer, Generate, i18nReducer, } from '@jsonforms/core';
import { attr, css, customElement, FASTElement, html, observable, when, } from '@microsoft/fast-element';
import { genesisErrorTranslator } from '../utils/translation';
const template = html `
  <template>
    ${when((x) => x.jsonforms && x.dispatch && x.props, html `
        <dispatch-renderer
          :jsonforms=${(x) => x.jsonforms}
          :dispatch=${(x) => x.dispatch}
          :props=${(x) => x.props}
          ?submitted=${(x) => x.submitted}
        />
      `)}
  </template>
`;
const styles = css ``;
const isObject = (elem) => {
    return elem && typeof elem === 'object';
};
const errorTranslator = (error, t, uischema) => {
    var _a, _b, _c, _d;
    return ((_d = (_c = (_b = (_a = uischema === null || uischema === void 0 ? void 0 : uischema.options) === null || _a === void 0 ? void 0 : _a.i18n) === null || _b === void 0 ? void 0 : _b.error) === null || _c === void 0 ? void 0 : _c[error.keyword]) !== null && _d !== void 0 ? _d : genesisErrorTranslator(error, t, uischema));
};
let JSONForms = class JSONForms extends FASTElement {
    constructor() {
        super(...arguments);
        this.dispatch = (action) => {
            this.jsonforms = Object.assign(Object.assign({}, this.jsonforms), { core: coreReducer(this.jsonforms.core, action) });
            this.$emit('data-change', {
                data: this.jsonforms.core.data,
                errors: this.jsonforms.core.errors,
            });
        };
        /**
         * Performs client-side validation by running the validator defined in the UI schema.
         * @param uischema the UI schema
         * @returns ErrorObject[] that will be passed to JsonFormsCore as additionalErrors
         */
        this.validate = (uischema) => {
            var _a, _b, _c;
            const data = (_b = (_a = this.jsonforms) === null || _a === void 0 ? void 0 : _a.core) === null || _b === void 0 ? void 0 : _b.data;
            if (!data)
                return [];
            const errors = [];
            (_c = uischema === null || uischema === void 0 ? void 0 : uischema.elements) === null || _c === void 0 ? void 0 : _c.forEach((e) => {
                var _a, _b, _c, _d;
                const validator = (_a = e === null || e === void 0 ? void 0 : e.options) === null || _a === void 0 ? void 0 : _a.validateFn;
                if (typeof validator !== 'function')
                    return;
                const path = (_c = (_b = e === null || e === void 0 ? void 0 : e.scope) === null || _b === void 0 ? void 0 : _b.split('/')) === null || _c === void 0 ? void 0 : _c.pop();
                const label = e === null || e === void 0 ? void 0 : e.label;
                let newErrors = (_d = validator(data, path, label)) !== null && _d !== void 0 ? _d : [];
                // the validator function is supposed to return an array of errors but let's not explode if it returns a single one
                if (!Array.isArray(newErrors)) {
                    newErrors = [newErrors];
                }
                errors.push(...newErrors);
            });
            return errors;
        };
    }
    schemaChanged() {
        var _a, _b, _c, _d;
        if (!this.schema) {
            return;
        }
        const uischemaToUse = (_a = this.uischema) !== null && _a !== void 0 ? _a : Generate.uiSchema(this.schema);
        if (!this.uischema) {
            console.log('UI schema not provided. Auto generated schema:', uischemaToUse);
        }
        const additionalErrors = this.validate(uischemaToUse);
        const initCore = () => {
            const initialCore = {
                data: this.data,
                schema: this.schema,
                uischema: uischemaToUse,
            };
            const core = coreReducer(initialCore, Actions.init(this.data, this.schema, uischemaToUse, {
                validationMode: this.validationMode || 'ValidateAndShow',
                ajv: this.ajv,
                additionalErrors,
            }));
            return core;
        };
        this.jsonforms = {
            core: initCore(),
            config: configReducer(undefined, Actions.setConfig(this.config)),
            i18n: i18nReducer(this.i18n, Actions.updateI18n((_b = this.i18n) === null || _b === void 0 ? void 0 : _b.locale, (_c = this.i18n) === null || _c === void 0 ? void 0 : _c.translate, ((_d = this.i18n) === null || _d === void 0 ? void 0 : _d.translateError) || errorTranslator)),
            renderers: this.renderers,
            readonly: this.readonly,
        };
        this.$emit('data-change', {
            data: this.jsonforms.core.data,
            errors: this.jsonforms.core.errors,
        });
    }
    uischemaChanged() {
        this.schemaChanged();
    }
    dataChanged() {
        this.schemaChanged();
    }
    renderersChanged() {
        this.schemaChanged();
    }
    validationModeChanged() {
        this.schemaChanged();
    }
    ajvChanged() {
        this.schemaChanged();
    }
    readonlyChanged() {
        this.schemaChanged();
    }
    configChanged() {
        this.schemaChanged();
    }
    get props() {
        var _a;
        if (!this.schema && !this.uischema) {
            return undefined;
        }
        const uischema = (_a = this.uischema) !== null && _a !== void 0 ? _a : Generate.uiSchema(this.schema);
        return {
            uischema,
            schema: this.schema,
            path: '',
            enabled: true,
            visible: true,
        };
    }
};
__decorate([
    attr({ mode: 'boolean' })
], JSONForms.prototype, "submitted", void 0);
__decorate([
    observable
], JSONForms.prototype, "jsonforms", void 0);
__decorate([
    observable
], JSONForms.prototype, "i18n", void 0);
__decorate([
    observable
], JSONForms.prototype, "schema", void 0);
__decorate([
    observable
], JSONForms.prototype, "uischema", void 0);
__decorate([
    observable
], JSONForms.prototype, "data", void 0);
__decorate([
    observable
], JSONForms.prototype, "renderers", void 0);
__decorate([
    observable
], JSONForms.prototype, "validationMode", void 0);
__decorate([
    observable
], JSONForms.prototype, "ajv", void 0);
__decorate([
    attr({ mode: 'boolean' })
], JSONForms.prototype, "readonly", void 0);
__decorate([
    observable
], JSONForms.prototype, "config", void 0);
JSONForms = __decorate([
    customElement({
        name: 'json-forms',
        template: template,
        styles: styles,
    })
], JSONForms);
export { JSONForms };
//# sourceMappingURL=json-forms.js.map