import { Host, h } from "@stencil/core";
import { derivedId, onBoolValueChanged } from '../../utils/utils';
import { NativeValidationStrategy } from '../../utils/native-validation-strategy';
let typeAheadId = 0;
export class TypeAhead {
    constructor() {
        this.optionListListener = (e) => this.onSelect(e);
        this.expanded = false;
        this.query = '';
        /**
         * Is the select disabled
         */
        this.disabled = false;
        /**
         * The select id
         */
        this.inputId = `anj-ta-${typeAheadId++}`;
        /**
         * The name of the select
         */
        this.name = this.inputId;
        /**
         * If true, the user cannot modify the value. Defaults to `false`.
         */
        this.readonly = false;
        /**
         * If true, the user must fill in a value before submitting a form.
         */
        this.required = false;
        /**
         * If true, the typeahead with look like a filter but still have a dropdown.
         */
        this.search = false;
        /**
         * @internal
         * The validation strategy to use
         */
        this.validationStrategy = new NativeValidationStrategy();
    }
    invalidChanged(newVal, oldVal) {
        onBoolValueChanged(newVal, oldVal, this.anjInvalid.emit);
    }
    valueChanged() {
        this.setInputValue();
        this.anjChange.emit({ value: this.value });
    }
    disconnectedCallback() {
        this.unbindOptionList();
        this.overlay = null;
    }
    onInputDidLoad(event) {
        this.input = event.target;
        if (this.value) {
            this.setInputValue();
        }
    }
    async onFocus() {
        this.overlay = this.bindOverlay();
        // if the overlay just closed this *should* not exist, so that's our sign.
        if (!this.overlay)
            return;
        if (!this.optionList) {
            this.optionList = this.bindOptionList();
        }
        this.activeOption = await this.optionList.reset();
        await this.overlay.open(this.element);
        this.expanded = true;
    }
    async onBlur() {
        if (this.overlay) {
            await this.overlay.close();
        }
        this.expanded = false;
        return this.validationStrategy.onTouched(this.element);
    }
    async onSelect(event) {
        this.value = event.detail;
        await this.onBlur();
        this.setQuery('');
    }
    onValidChange(event) {
        this.invalid = event.detail;
    }
    /**
     * Checks the native element validity use native validators
     */
    async checkValidity() {
        const valid = await this.input.checkValidity();
        this.invalid = !valid;
        return valid;
    }
    async onKeyDown(event) {
        if (!this.expanded) {
            await this.onFocus();
        }
        if (this.expanded && event.key === 'Escape') {
            return this.overlay.close();
        }
        this.activeOption = await this.optionList.onKeyAction(event);
    }
    onChange(event) {
        event.stopPropagation();
        if (this.expanded || event.detail.value === '') {
            this.setQuery(event.detail.value);
        }
        if (event.detail.value === '') {
            this.value = '';
        }
    }
    setInputValue() {
        this.input.value = this.display && this.value ? this.value[this.display] : this.value;
    }
    setQuery(query) {
        this.query = query;
        this.anjQuery.emit(this.query);
    }
    ariaActive() {
        if (this.expanded && this.activeOption) {
            return this.activeOption.id;
        }
        return null;
    }
    bindOptionList() {
        const el = this.element.querySelector('anj-option-list');
        if (el) {
            el.addEventListener('anjSelect', this.optionListListener);
        }
        return el;
    }
    unbindOptionList() {
        if (!this.optionList)
            return;
        this.optionList.removeEventListener('anjSelect', this.optionListListener);
        this.optionList = null;
    }
    bindOverlay() {
        return this.element.querySelector('anj-overlay');
    }
    render() {
        const olClass = this.optionList && this.optionList.options && this.optionList.options.length > 0
            ? 'anj-dropdown-menu anj-select-menu' : 'anj-opts-hidden';
        const optListId = derivedId(this.inputId, 'options');
        const overlayWidth = this.element.offsetWidth;
        const inputAttrs = {
            'aria-autocomplete': 'list',
            'aria-controls': optListId,
            'aria-activedescendant': this.ariaActive()
        };
        return (h(Host, null,
            h("anj-input", { attrs: inputAttrs, "aria-owns": derivedId(this.inputId, 'options'), "aria-haspopup": "listbox", "aria-expanded": `${!!this.expanded}`, placeholder: this.placeholder, clearable: true, debounce: 300, role: "combobox", disabled: this.disabled, readonly: this.readonly, required: this.required, onKeyDown: (event) => this.onKeyDown(event), onAnjChange: (event) => this.onChange(event), validationStrategy: this.validationStrategy }, this.search ?
                h("anj-input-prefix", null,
                    h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24" },
                        h("path", { d: "M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" }))) : undefined),
            h("anj-overlay", { class: olClass, placement: "bottom-start", style: { 'min-width': `${overlayWidth}px` } },
                h("anj-option-list", { id: optListId, role: "listbox", "aria-label": optListId },
                    h("slot", null)))));
    }
    static get is() { return "anj-type-ahead"; }
    static get encapsulation() { return "scoped"; }
    static get originalStyleUrls() { return {
        "$": ["type-ahead.scss"]
    }; }
    static get styleUrls() { return {
        "$": ["type-ahead.css"]
    }; }
    static get properties() { return {
        "disabled": {
            "type": "boolean",
            "mutable": false,
            "complexType": {
                "original": "boolean",
                "resolved": "boolean",
                "references": {}
            },
            "required": false,
            "optional": false,
            "docs": {
                "tags": [],
                "text": "Is the select disabled"
            },
            "attribute": "disabled",
            "reflect": false,
            "defaultValue": "false"
        },
        "display": {
            "type": "string",
            "mutable": false,
            "complexType": {
                "original": "string",
                "resolved": "string",
                "references": {}
            },
            "required": false,
            "optional": false,
            "docs": {
                "tags": [],
                "text": "Prop to display for a selected item"
            },
            "attribute": "display",
            "reflect": false
        },
        "inputId": {
            "type": "string",
            "mutable": false,
            "complexType": {
                "original": "string",
                "resolved": "string",
                "references": {}
            },
            "required": false,
            "optional": false,
            "docs": {
                "tags": [],
                "text": "The select id"
            },
            "attribute": "input-id",
            "reflect": false,
            "defaultValue": "`anj-ta-${typeAheadId++}`"
        },
        "invalid": {
            "type": "boolean",
            "mutable": true,
            "complexType": {
                "original": "boolean",
                "resolved": "boolean",
                "references": {}
            },
            "required": false,
            "optional": false,
            "docs": {
                "tags": [],
                "text": "Whether the control is valid"
            },
            "attribute": "invalid",
            "reflect": true
        },
        "name": {
            "type": "string",
            "mutable": false,
            "complexType": {
                "original": "string",
                "resolved": "string",
                "references": {}
            },
            "required": false,
            "optional": false,
            "docs": {
                "tags": [],
                "text": "The name of the select"
            },
            "attribute": "name",
            "reflect": false,
            "defaultValue": "this.inputId"
        },
        "placeholder": {
            "type": "string",
            "mutable": false,
            "complexType": {
                "original": "string",
                "resolved": "string",
                "references": {}
            },
            "required": false,
            "optional": false,
            "docs": {
                "tags": [],
                "text": "Value of the input placeholder"
            },
            "attribute": "placeholder",
            "reflect": false
        },
        "readonly": {
            "type": "boolean",
            "mutable": false,
            "complexType": {
                "original": "boolean",
                "resolved": "boolean",
                "references": {}
            },
            "required": false,
            "optional": false,
            "docs": {
                "tags": [],
                "text": "If true, the user cannot modify the value. Defaults to `false`."
            },
            "attribute": "readonly",
            "reflect": false,
            "defaultValue": "false"
        },
        "required": {
            "type": "boolean",
            "mutable": false,
            "complexType": {
                "original": "boolean",
                "resolved": "boolean",
                "references": {}
            },
            "required": false,
            "optional": false,
            "docs": {
                "tags": [],
                "text": "If true, the user must fill in a value before submitting a form."
            },
            "attribute": "required",
            "reflect": false,
            "defaultValue": "false"
        },
        "search": {
            "type": "boolean",
            "mutable": false,
            "complexType": {
                "original": "boolean",
                "resolved": "boolean",
                "references": {}
            },
            "required": false,
            "optional": false,
            "docs": {
                "tags": [],
                "text": "If true, the typeahead with look like a filter but still have a dropdown."
            },
            "attribute": "search",
            "reflect": true,
            "defaultValue": "false"
        },
        "validationStrategy": {
            "type": "unknown",
            "mutable": false,
            "complexType": {
                "original": "NativeValidationStrategy",
                "resolved": "NativeValidationStrategy",
                "references": {
                    "NativeValidationStrategy": {
                        "location": "import",
                        "path": "../../utils/native-validation-strategy"
                    }
                }
            },
            "required": false,
            "optional": false,
            "docs": {
                "tags": [{
                        "text": "The validation strategy to use",
                        "name": "internal"
                    }],
                "text": ""
            },
            "defaultValue": "new NativeValidationStrategy()"
        },
        "value": {
            "type": "any",
            "mutable": true,
            "complexType": {
                "original": "any | null",
                "resolved": "any",
                "references": {}
            },
            "required": false,
            "optional": true,
            "docs": {
                "tags": [],
                "text": "the value of the select"
            },
            "attribute": "value",
            "reflect": false
        }
    }; }
    static get states() { return {
        "activeOption": {},
        "expanded": {},
        "query": {}
    }; }
    static get events() { return [{
            "method": "anjChange",
            "name": "anjChange",
            "bubbles": true,
            "cancelable": true,
            "composed": true,
            "docs": {
                "tags": [],
                "text": "Emitted when the value has changed."
            },
            "complexType": {
                "original": "SelectChangeEvent",
                "resolved": "SelectChangeEvent",
                "references": {
                    "SelectChangeEvent": {
                        "location": "import",
                        "path": "../../types/types"
                    }
                }
            }
        }, {
            "method": "anjInvalid",
            "name": "anjInvalid",
            "bubbles": true,
            "cancelable": true,
            "composed": true,
            "docs": {
                "tags": [],
                "text": "Emitted when invalid status changes."
            },
            "complexType": {
                "original": "any",
                "resolved": "any",
                "references": {}
            }
        }, {
            "method": "anjQuery",
            "name": "anjQuery",
            "bubbles": true,
            "cancelable": true,
            "composed": true,
            "docs": {
                "tags": [],
                "text": "Emitted when query changes"
            },
            "complexType": {
                "original": "any",
                "resolved": "any",
                "references": {}
            }
        }]; }
    static get methods() { return {
        "checkValidity": {
            "complexType": {
                "signature": "() => Promise<boolean>",
                "parameters": [],
                "references": {
                    "Promise": {
                        "location": "global"
                    }
                },
                "return": "Promise<boolean>"
            },
            "docs": {
                "text": "Checks the native element validity use native validators",
                "tags": []
            }
        }
    }; }
    static get elementRef() { return "element"; }
    static get watchers() { return [{
            "propName": "invalid",
            "methodName": "invalidChanged"
        }, {
            "propName": "value",
            "methodName": "valueChanged"
        }]; }
    static get listeners() { return [{
            "name": "anjControlDidLoad",
            "method": "onInputDidLoad",
            "target": undefined,
            "capture": false,
            "passive": false
        }, {
            "name": "anjFocus",
            "method": "onFocus",
            "target": undefined,
            "capture": false,
            "passive": false
        }, {
            "name": "anjBlur",
            "method": "onBlur",
            "target": undefined,
            "capture": false,
            "passive": false
        }, {
            "name": "anjSelect",
            "method": "onSelect",
            "target": undefined,
            "capture": false,
            "passive": false
        }, {
            "name": "anjInvalid",
            "method": "onValidChange",
            "target": undefined,
            "capture": false,
            "passive": false
        }]; }
}
