var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, privateMap, value) {
    if (!privateMap.has(receiver)) {
        throw new TypeError("attempted to set private field on non-instance");
    }
    privateMap.set(receiver, value);
    return value;
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, privateMap) {
    if (!privateMap.has(receiver)) {
        throw new TypeError("attempted to get private field on non-instance");
    }
    return privateMap.get(receiver);
};
var _el, _languages, _language;
export class InputHandler {
    constructor(el) {
        _el.set(this, void 0);
        _languages.set(this, []);
        _language.set(this, '');
        this.input = (event, options = {}) => {
            const { localize, on, transform } = options;
            const target = event.target;
            const path = (transform === null || transform === void 0 ? void 0 : transform.path) || target.name;
            const value = transform ? transform.get(target.value) : target.value;
            if (on)
                on(value, path);
            // Capturing and re-emitting the event to ensure the target is always the
            // specified element. Doing this allows slot elements to trigger an input
            // event from the parent module.
            event.stopPropagation();
            this.set(path, value, { emit: true, localize });
        };
        __classPrivateFieldSet(this, _el, el);
    }
    get label() {
        return 'label' in __classPrivateFieldGet(this, _el) ? __classPrivateFieldGet(this, _el).label : {};
    }
    get value() {
        return 'template' in __classPrivateFieldGet(this, _el) ? __classPrivateFieldGet(this, _el).template : __classPrivateFieldGet(this, _el).value;
    }
    set value(val) {
        if ('template' in __classPrivateFieldGet(this, _el))
            return;
        else
            __classPrivateFieldGet(this, _el).value = val;
    }
    create(path, el) {
        const props = this.prop(path);
        for (const key of Object.keys(props)) {
            const value = props[key];
            if (value != undefined)
                el[key] = value;
        }
    }
    get(path, options = {}) {
        const { localize, obj, transform, type = 'value' } = options;
        const data = obj || (type === 'value' ? this.value : this.label);
        const localePath = this.getLocalePath((transform === null || transform === void 0 ? void 0 : transform.path) || path, localize);
        const parts = localePath.split('.');
        const prefix = type === 'value' ? '' : type;
        return parts.reduce((o, x, i) => {
            if (i + 1 == parts.length)
                x = prefix ? `${prefix}${x.slice(0, 1).toUpperCase()}${x.slice(1)}` : x;
            return transform ? transform.set(o[x]) : o[x];
        }, data);
    }
    prop(path, options = {}) {
        const { label: obj, localize, transform } = options;
        return {
            label: this.tryGet(path, { type: 'label', obj }),
            name: path,
            placeholder: this.tryGet(path, { type: 'placeholder', obj }),
            value: this.tryGet(path, { transform, localize }) ||
                (options.default && options.default()),
            onInput: (e) => this.input(e, options)
        };
    }
    set(path, value, options = {}) {
        const localePath = this.getLocalePath(path, options.localize);
        this.value = this.update(localePath, value, this.value);
        if (options.emit)
            this.emit();
        return value;
    }
    t(path, options = {}) {
        return (this.tryGet(path, Object.assign(Object.assign({}, options), { localize: true })) ||
            this.get(path, Object.assign(Object.assign({}, options), { localize: false })));
    }
    setLanguage(languages, language) {
        __classPrivateFieldSet(this, _languages, languages);
        __classPrivateFieldSet(this, _language, language);
    }
    tryGet(path, options = {}) {
        try {
            return this.get(path, options);
        }
        catch (e) {
            return undefined;
        }
    }
    emit() {
        const e = new Event('input', { bubbles: true, composed: true });
        __classPrivateFieldGet(this, _el).dispatchEvent(e);
    }
    getLocalePath(path, localize = false) {
        if (!localize)
            return path;
        const fallback = __classPrivateFieldGet(this, _languages)[0] && __classPrivateFieldGet(this, _languages)[0].key;
        const language = __classPrivateFieldGet(this, _language) || fallback;
        const locale = !!language && language !== fallback
            ? 'i18n.' + __classPrivateFieldGet(this, _language)
            : undefined;
        return locale ? [locale, path].join('.') : path;
    }
    update(path, value, obj = {}) {
        const [key, ...rest] = path.split('.');
        return rest.length
            ? Object.assign(Object.assign({}, obj), { [key]: this.update(rest.join('.'), value, obj[key]) }) : Object.assign(Object.assign({}, obj), { [key]: value });
    }
}
_el = new WeakMap(), _languages = new WeakMap(), _language = new WeakMap();
