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 __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 _id, _initialized, _initialValue, _inputCreator, _menu, _popper, _prevTagValue, _options;
import { library } from '@fortawesome/fontawesome-svg-core';
import { faAngleDown, faAngleUp } from '@fortawesome/free-solid-svg-icons';
import { createPopper } from '@popperjs/core';
import { h } from "@stencil/core";
import { getInputCreator } from '../bce-input-creator/input-creator';
import { MenuControl } from '../../utils/menu-control';
library.add(faAngleDown, faAngleUp);
export class Select {
    constructor() {
        this.type = 'checkbox';
        _id.set(this, window.BCE.generateId());
        _initialized.set(this, false);
        _initialValue.set(this, this.value);
        _inputCreator.set(this, getInputCreator(this, err => (this.error = !!err)));
        _menu.set(this, void 0);
        _popper.set(this, void 0);
        _prevTagValue.set(this, '');
        _options.set(this, []);
        this.handleClick = () => {
            switch (this.type) {
                case 'checkbox':
                case 'filter':
                    this.value = __classPrivateFieldGet(this, _options).filter(option => !!option.value && !!option.checked)
                        .map(option => option.value);
                    return;
                case 'choice':
                case 'radio':
                    const option = __classPrivateFieldGet(this, _options).find(option => option.checked);
                    this.value = option ? option.value : null;
                    return;
            }
        };
        this.handleFilter = (event) => {
            var _a, _b;
            const value = event.target.value || '';
            const filter = value.toLowerCase().trim();
            for (const option of __classPrivateFieldGet(this, _options)) {
                const check1 = option.innerText.toLowerCase();
                const check2 = (_a = option.value) === null || _a === void 0 ? void 0 : _a.toLowerCase();
                const visible = check1.indexOf(filter) >= 0 ||
                    (check2 ? check2.indexOf(filter) >= 0 : false);
                option.style.display = visible ? '' : 'none';
            }
            const filtered = __classPrivateFieldGet(this, _options).filter(o => o.style.display !== 'none');
            (_b = __classPrivateFieldGet(this, _menu)) === null || _b === void 0 ? void 0 : _b.setItems(filtered);
            event.stopPropagation();
        };
        this.handleSlotChange = () => {
            // Remove existing event listeners
            for (const option of __classPrivateFieldGet(this, _options))
                this.removeEventHandlers(option);
            // Load new options
            const children = Array.from(this.el.childNodes);
            __classPrivateFieldSet(this, _options, children.filter(n => ['BCE-CHIP', 'BCE-OPTION'].indexOf(n.nodeName) >= 0));
            // Initialize options & attach event listeners
            for (const option of __classPrivateFieldGet(this, _options)) {
                option.type = this.type;
                option.name = this.name || __classPrivateFieldGet(this, _id);
                if (option.nodeName === 'BCE-OPTION')
                    option.allowNull = this.allowNull;
                this.attachEventHandlers(option);
            }
            if (__classPrivateFieldGet(this, _menu))
                __classPrivateFieldGet(this, _menu).setItems(__classPrivateFieldGet(this, _options));
        };
        this.handleTagKeyDown = (event) => {
            const input = event.target;
            __classPrivateFieldSet(this, _prevTagValue, input.value);
        };
        this.handleTagKeyUp = (event) => {
            if (!Array.isArray(this.value))
                this.value = [];
            const input = event.target;
            const value = input.value.trim();
            switch (event.key) {
                case 'Backspace': {
                    if (__classPrivateFieldGet(this, _prevTagValue).length)
                        return;
                    this.value = this.value.slice(0, -1);
                    this.dispatchInputEvent();
                    return;
                }
                case 'Enter': {
                    this.value = [...this.value, value];
                    input.value = '';
                    this.dispatchInputEvent();
                    return;
                }
            }
        };
        this.handleTagRemove = (event) => {
            const chip = event.target;
            const value = (chip.value || '').trim();
            this.value = Array.isArray(this.value)
                ? this.value.filter(v => v !== value)
                : [];
            this.dispatchInputEvent();
        };
        this.ignoreEvent = (event) => {
            event.stopPropagation();
        };
    }
    watchDisabled() {
        for (const option of __classPrivateFieldGet(this, _options))
            option.disabled = this.disabled;
    }
    watchValue(value) {
        if (__classPrivateFieldGet(this, _initialized))
            __classPrivateFieldGet(this, _inputCreator).handleInput();
        switch (this.type) {
            case 'checkbox':
            case 'filter':
                const values = Array.isArray(value)
                    ? value
                    : (value && value.split(',').map(v => v.trim())) || [];
                for (const option of __classPrivateFieldGet(this, _options))
                    option.checked = values.indexOf(option.value || '') >= 0;
                return;
            case 'dropdown':
                this.updateDropdown();
            case 'choice':
            case 'radio':
                for (const option of __classPrivateFieldGet(this, _options))
                    option.checked = this.value === option.value;
                return;
            case 'input':
                this.value = Array.isArray(value)
                    ? value
                    : (value === null || value === void 0 ? void 0 : value.split(',').map(v => v.trim()).filter(Boolean)) || [];
                return;
        }
    }
    handleChip(event) {
        const dispatch = !equal(this.value || null, event.detail || null);
        this.value = event.detail;
        if (dispatch) {
            const e = new Event('input', { bubbles: true, composed: true });
            this.el.dispatchEvent(e);
        }
    }
    async next() {
        return __classPrivateFieldGet(this, _menu) && __classPrivateFieldGet(this, _menu).next();
    }
    async prev() {
        return __classPrivateFieldGet(this, _menu) && __classPrivateFieldGet(this, _menu).prev();
    }
    async reset() {
        this.value = __classPrivateFieldGet(this, _initialValue);
        __classPrivateFieldGet(this, _inputCreator).reset();
    }
    async toggle(active = !this.active) {
        if (this.type !== 'dropdown')
            return;
        this.active = active;
        if (__classPrivateFieldGet(this, _popper))
            __classPrivateFieldGet(this, _popper).update();
    }
    async validate(silent = false) {
        return __classPrivateFieldGet(this, _inputCreator).validate(silent);
    }
    attachEventHandlers(el) {
        el.addEventListener('click', this.handleClick);
    }
    dispatchInputEvent() {
        const e = new Event('input', { bubbles: true, composed: true });
        this.el.dispatchEvent(e);
    }
    removeEventHandlers(el) {
        el.removeEventListener('click', this.handleClick);
    }
    updateDropdown() {
        const input = this.el.shadowRoot.querySelector('bce-input');
        if (!input)
            return;
        if (!this.value) {
            input.value = '';
            __classPrivateFieldGet(this, _menu).setValue(undefined);
        }
        const option = __classPrivateFieldGet(this, _options).find(o => o.value === this.value);
        if (option) {
            input.value = (option.innerText || '').trim();
            if (__classPrivateFieldGet(this, _menu))
                __classPrivateFieldGet(this, _menu).setValue(option);
        }
    }
    componentWillLoad() {
        this.watchValue(this.value);
    }
    componentDidLoad() {
        if (this.type === 'dropdown') {
            const root = this.el.shadowRoot;
            const ref = '.trigger bce-input';
            const reference = root.querySelector(ref);
            const dropdown = root.querySelector("[role='listbox']");
            __classPrivateFieldSet(this, _menu, new MenuControl({
                parent: this.el,
                trigger: reference,
                onToggle: this.toggle.bind(this),
                listbox: true
            }));
            // Create popper.js dropdown
            __classPrivateFieldSet(this, _popper, createPopper(reference, dropdown, {
                modifiers: [{ name: 'offset', options: { offset: [0, 2] } }],
                placement: 'bottom-start',
                strategy: 'fixed'
            }));
            // Patch popper.js fixed position
            new window.ResizeObserver(() => {
                const { x, width } = reference.getBoundingClientRect();
                const match = dropdown.style.transform.match(/^translate3d\((\d+)px/);
                const offset = match ? parseFloat(match[1]) : 0;
                dropdown.style.left = `${x - offset}px`;
                dropdown.style.width = width + 'px';
            }).observe(reference);
        }
        const slot = this.el.shadowRoot.querySelector('slot');
        slot === null || slot === void 0 ? void 0 : slot.addEventListener('slotchange', this.handleSlotChange);
        this.handleSlotChange();
        this.watchDisabled();
        this.watchValue(this.value);
        __classPrivateFieldSet(this, _initialized, true);
    }
    componentDidUnload() {
        if (__classPrivateFieldGet(this, _popper))
            __classPrivateFieldGet(this, _popper).destroy();
        if (__classPrivateFieldGet(this, _menu))
            __classPrivateFieldGet(this, _menu).dispose();
    }
    renderDropdown() {
        const InputCreator = __classPrivateFieldGet(this, _inputCreator);
        return (h(InputCreator, null,
            h("div", { class: "trigger" },
                h("bce-input", { a11yAriaHaspopup: "listbox", a11yAriaExpanded: this.active, placeholder: this.placeholder, "data-active": this.active, onInput: this.handleFilter }),
                h("bce-button", { design: "text", icon: this.active ? 'fas:angle-up' : 'fas:angle-down', tabIndex: -1 })),
            h("ul", { role: "listbox", "data-active": this.active },
                h("slot", null))));
    }
    renderFieldset() {
        const InputCreator = __classPrivateFieldGet(this, _inputCreator);
        const radio = this.type === 'choice' || this.type === 'radio';
        const role = radio ? 'radiogroup' : 'group';
        return (h(InputCreator, null,
            h("div", { class: "fieldset", role: role, "aria-label": this.label },
                h("slot", null))));
    }
    renderTag(value) {
        return (h("bce-chip", { disabled: this.disabled, removable: true, type: "input", value: value, onRemove: this.handleTagRemove }, value));
    }
    renderTagInput() {
        const InputCreator = __classPrivateFieldGet(this, _inputCreator);
        return (h(InputCreator, null,
            h("div", { class: "container" },
                Array.isArray(this.value) && this.value.map(v => this.renderTag(v)),
                h("input", { onInput: this.ignoreEvent, onKeyUp: this.handleTagKeyUp, onKeyDown: this.handleTagKeyDown }))));
    }
    render() {
        switch (this.type) {
            case 'action':
            case 'checkbox':
            case 'choice':
            case 'filter':
            case 'radio':
                return this.renderFieldset();
            case 'dropdown':
                return this.renderDropdown();
            case 'input':
                return this.renderTagInput();
        }
    }
    static get is() { return "bce-select"; }
    static get encapsulation() { return "shadow"; }
    static get originalStyleUrls() { return {
        "$": ["bce-select.scss"]
    }; }
    static get styleUrls() { return {
        "$": ["bce-select.css"]
    }; }
    static get properties() { return {
        "active": {
            "type": "boolean",
            "mutable": true,
            "complexType": {
                "original": "boolean",
                "resolved": "boolean",
                "references": {}
            },
            "required": false,
            "optional": true,
            "docs": {
                "tags": [],
                "text": ""
            },
            "attribute": "active",
            "reflect": true
        },
        "allowNull": {
            "type": "boolean",
            "mutable": false,
            "complexType": {
                "original": "boolean",
                "resolved": "boolean",
                "references": {}
            },
            "required": false,
            "optional": true,
            "docs": {
                "tags": [],
                "text": ""
            },
            "attribute": "allow-null",
            "reflect": true
        },
        "center": {
            "type": "boolean",
            "mutable": false,
            "complexType": {
                "original": "boolean",
                "resolved": "boolean",
                "references": {}
            },
            "required": false,
            "optional": true,
            "docs": {
                "tags": [],
                "text": ""
            },
            "attribute": "center",
            "reflect": true
        },
        "design": {
            "type": "string",
            "mutable": false,
            "complexType": {
                "original": "'matrix'",
                "resolved": "\"matrix\"",
                "references": {}
            },
            "required": false,
            "optional": true,
            "docs": {
                "tags": [],
                "text": ""
            },
            "attribute": "design",
            "reflect": true
        },
        "disabled": {
            "type": "boolean",
            "mutable": false,
            "complexType": {
                "original": "boolean",
                "resolved": "boolean",
                "references": {}
            },
            "required": false,
            "optional": true,
            "docs": {
                "tags": [],
                "text": ""
            },
            "attribute": "disabled",
            "reflect": true
        },
        "error": {
            "type": "boolean",
            "mutable": false,
            "complexType": {
                "original": "boolean",
                "resolved": "boolean",
                "references": {}
            },
            "required": false,
            "optional": true,
            "docs": {
                "tags": [],
                "text": ""
            },
            "attribute": "error",
            "reflect": true
        },
        "hasFocus": {
            "type": "boolean",
            "mutable": false,
            "complexType": {
                "original": "boolean",
                "resolved": "boolean",
                "references": {}
            },
            "required": false,
            "optional": true,
            "docs": {
                "tags": [],
                "text": ""
            },
            "attribute": "focus",
            "reflect": true
        },
        "info": {
            "type": "string",
            "mutable": false,
            "complexType": {
                "original": "string",
                "resolved": "string",
                "references": {}
            },
            "required": false,
            "optional": true,
            "docs": {
                "tags": [],
                "text": ""
            },
            "attribute": "info",
            "reflect": true
        },
        "label": {
            "type": "string",
            "mutable": false,
            "complexType": {
                "original": "string",
                "resolved": "string",
                "references": {}
            },
            "required": false,
            "optional": true,
            "docs": {
                "tags": [],
                "text": ""
            },
            "attribute": "label",
            "reflect": true
        },
        "name": {
            "type": "string",
            "mutable": false,
            "complexType": {
                "original": "string",
                "resolved": "string",
                "references": {}
            },
            "required": false,
            "optional": true,
            "docs": {
                "tags": [],
                "text": ""
            },
            "attribute": "name",
            "reflect": true
        },
        "placeholder": {
            "type": "string",
            "mutable": false,
            "complexType": {
                "original": "string",
                "resolved": "string",
                "references": {}
            },
            "required": false,
            "optional": true,
            "docs": {
                "tags": [],
                "text": ""
            },
            "attribute": "placeholder",
            "reflect": true
        },
        "tooltip": {
            "type": "string",
            "mutable": false,
            "complexType": {
                "original": "string",
                "resolved": "string",
                "references": {}
            },
            "required": false,
            "optional": true,
            "docs": {
                "tags": [],
                "text": ""
            },
            "attribute": "tooltip",
            "reflect": false
        },
        "type": {
            "type": "string",
            "mutable": false,
            "complexType": {
                "original": "SelectType",
                "resolved": "\"action\" | \"checkbox\" | \"choice\" | \"dropdown\" | \"filter\" | \"input\" | \"radio\"",
                "references": {
                    "SelectType": {
                        "location": "import",
                        "path": "../../models/select-type"
                    }
                }
            },
            "required": false,
            "optional": false,
            "docs": {
                "tags": [],
                "text": ""
            },
            "attribute": "type",
            "reflect": true,
            "defaultValue": "'checkbox'"
        },
        "validation": {
            "type": "string",
            "mutable": false,
            "complexType": {
                "original": "string",
                "resolved": "string",
                "references": {}
            },
            "required": false,
            "optional": true,
            "docs": {
                "tags": [],
                "text": ""
            },
            "attribute": "validation",
            "reflect": true
        },
        "value": {
            "type": "string",
            "mutable": true,
            "complexType": {
                "original": "SelectValue",
                "resolved": "string | string[]",
                "references": {
                    "SelectValue": {
                        "location": "import",
                        "path": "../../models/select-value"
                    }
                }
            },
            "required": false,
            "optional": true,
            "docs": {
                "tags": [],
                "text": ""
            },
            "attribute": "value",
            "reflect": false
        }
    }; }
    static get methods() { return {
        "next": {
            "complexType": {
                "signature": "() => Promise<void>",
                "parameters": [],
                "references": {
                    "Promise": {
                        "location": "global"
                    }
                },
                "return": "Promise<void>"
            },
            "docs": {
                "text": "",
                "tags": []
            }
        },
        "prev": {
            "complexType": {
                "signature": "() => Promise<void>",
                "parameters": [],
                "references": {
                    "Promise": {
                        "location": "global"
                    }
                },
                "return": "Promise<void>"
            },
            "docs": {
                "text": "",
                "tags": []
            }
        },
        "reset": {
            "complexType": {
                "signature": "() => Promise<void>",
                "parameters": [],
                "references": {
                    "Promise": {
                        "location": "global"
                    }
                },
                "return": "Promise<void>"
            },
            "docs": {
                "text": "",
                "tags": []
            }
        },
        "toggle": {
            "complexType": {
                "signature": "(active?: boolean) => Promise<void>",
                "parameters": [{
                        "tags": [],
                        "text": ""
                    }],
                "references": {
                    "Promise": {
                        "location": "global"
                    }
                },
                "return": "Promise<void>"
            },
            "docs": {
                "text": "",
                "tags": []
            }
        },
        "validate": {
            "complexType": {
                "signature": "(silent?: boolean) => Promise<ValidatorError[]>",
                "parameters": [{
                        "tags": [],
                        "text": ""
                    }],
                "references": {
                    "Promise": {
                        "location": "global"
                    },
                    "ValidatorError": {
                        "location": "import",
                        "path": "../../utils/validator"
                    }
                },
                "return": "Promise<ValidatorError[]>"
            },
            "docs": {
                "text": "",
                "tags": []
            }
        }
    }; }
    static get elementRef() { return "el"; }
    static get watchers() { return [{
            "propName": "disabled",
            "methodName": "watchDisabled"
        }, {
            "propName": "value",
            "methodName": "watchValue"
        }]; }
    static get listeners() { return [{
            "name": "bce-core:chip",
            "method": "handleChip",
            "target": undefined,
            "capture": false,
            "passive": false
        }, {
            "name": "bce-core:option",
            "method": "handleChip",
            "target": undefined,
            "capture": false,
            "passive": false
        }]; }
}
_id = new WeakMap(), _initialized = new WeakMap(), _initialValue = new WeakMap(), _inputCreator = new WeakMap(), _menu = new WeakMap(), _popper = new WeakMap(), _prevTagValue = new WeakMap(), _options = new WeakMap();
const equal = (a, b) => {
    if (typeof a !== typeof b)
        return false;
    if (!Array.isArray(a) || !Array.isArray(b))
        return a === b;
    if (a.length != b.length)
        return false;
    for (let i = 0; i < a.length; i++)
        if (a[i] !== b[i])
            return false;
    return true;
};
