import { Host, h } from "@stencil/core";
import { ActionKey, ActionKeys } from '../../utils/utils';
/** @internal */
export class OptionList {
    constructor() {
        /**
         * Tracks the active option
         */
        this.expanded = false;
    }
    updateActive(newOpt, oldOpt) {
        if (oldOpt) {
            oldOpt.active = false;
        }
        if (newOpt) {
            newOpt.active = true;
            this.scrollToActive(newOpt);
        }
    }
    async componentDidLoad() {
        await this.loadOptions();
    }
    /**
     * Responds to a given keydown event
     */
    async onKeyAction(event) {
        if (ActionKeys.includes(event.key)) {
            event.preventDefault();
            switch (event.key) {
                case ActionKey.ArrowDown:
                    this.activate();
                    break;
                case ActionKey.ArrowUp:
                    this.activate(-1);
                    break;
                case ActionKey.Enter:
                    this.select();
                    break;
                case ActionKey.Escape:
                    this.element.blur();
                    break;
            }
        }
        return this.active;
    }
    /**
     * Hack until https://github.com/ionic-team/stencil/issues/1218 is fixed
     * Once it is, completely remove the observer and use the commented-out events -r
     */
    // @Listen('anjOptionDidLoad')
    // @Listen('anjOptionDidUnload')
    async onOptionsChanged() {
        await this.loadOptions();
        return new Promise(resolve => {
            window.setTimeout(() => {
                if (this.options.length > 0) {
                    this.reset();
                }
                resolve();
            }, 20);
        });
    }
    /**
     * Reset the list
     */
    async reset(active = this.options[0]) {
        this.active = active;
        return this.active;
    }
    async select() {
        return this.active.select();
    }
    activate(increment = 1) {
        const selectable = this.options.filter(opt => !opt.disabled);
        const next = selectable[selectable.findIndex(opt => opt.active) + increment];
        if (next) {
            this.active = next;
        }
    }
    scrollToActive(option) {
        if (option.offsetTop + option.clientHeight > this.element.clientHeight + this.element.scrollTop) {
            this.element.scrollTop = option.offsetTop + option.clientHeight - this.element.clientHeight;
        }
        else if (option.offsetTop + option.clientHeight < this.element.scrollTop + this.element.clientHeight) {
            this.element.scrollTop = this.element.scrollTop - option.clientHeight > -1 ? this.element.scrollTop - option.clientHeight : 0;
        }
    }
    async loadOptions() {
        this.options = await Promise.all(Array.from(this.element.querySelectorAll('anj-option')).map(opt => opt.componentOnReady()));
        this.anjOptionsChange.emit(this.options);
    }
    render() {
        return (h(Host, { "aria-activedescendant": this.expanded && this.active ? this.active.id : null, role: "listbox", tabindex: "-1" },
            h("anj-observer", { incattrs: false },
                h("slot", null))));
    }
    static get is() { return "anj-option-list"; }
    static get originalStyleUrls() { return {
        "$": ["option-list.scss"]
    }; }
    static get styleUrls() { return {
        "$": ["option-list.css"]
    }; }
    static get properties() { return {
        "active": {
            "type": "unknown",
            "mutable": true,
            "complexType": {
                "original": "HTMLAnjOptionElement",
                "resolved": "HTMLAnjOptionElement",
                "references": {
                    "HTMLAnjOptionElement": {
                        "location": "global"
                    }
                }
            },
            "required": false,
            "optional": false,
            "docs": {
                "tags": [],
                "text": "Tracks the active option"
            }
        },
        "expanded": {
            "type": "boolean",
            "mutable": false,
            "complexType": {
                "original": "boolean",
                "resolved": "boolean",
                "references": {}
            },
            "required": false,
            "optional": false,
            "docs": {
                "tags": [],
                "text": "Tracks the active option"
            },
            "attribute": "expanded",
            "reflect": false,
            "defaultValue": "false"
        },
        "options": {
            "type": "unknown",
            "mutable": true,
            "complexType": {
                "original": "HTMLAnjOptionElement[]",
                "resolved": "HTMLAnjOptionElement[]",
                "references": {
                    "HTMLAnjOptionElement": {
                        "location": "global"
                    }
                }
            },
            "required": false,
            "optional": false,
            "docs": {
                "tags": [],
                "text": "Array of all options"
            }
        }
    }; }
    static get events() { return [{
            "method": "anjOptionsChange",
            "name": "anjOptionsChange",
            "bubbles": true,
            "cancelable": true,
            "composed": true,
            "docs": {
                "tags": [],
                "text": ""
            },
            "complexType": {
                "original": "HTMLAnjOptionElement[]",
                "resolved": "HTMLAnjOptionElement[]",
                "references": {
                    "HTMLAnjOptionElement": {
                        "location": "global"
                    }
                }
            }
        }]; }
    static get methods() { return {
        "onKeyAction": {
            "complexType": {
                "signature": "(event: KeyboardEvent) => Promise<HTMLAnjOptionElement>",
                "parameters": [{
                        "tags": [],
                        "text": ""
                    }],
                "references": {
                    "Promise": {
                        "location": "global"
                    },
                    "HTMLAnjOptionElement": {
                        "location": "global"
                    },
                    "KeyboardEvent": {
                        "location": "global"
                    }
                },
                "return": "Promise<HTMLAnjOptionElement>"
            },
            "docs": {
                "text": "Responds to a given keydown event",
                "tags": []
            }
        },
        "reset": {
            "complexType": {
                "signature": "(active?: HTMLAnjOptionElement) => Promise<HTMLAnjOptionElement>",
                "parameters": [{
                        "tags": [],
                        "text": ""
                    }],
                "references": {
                    "Promise": {
                        "location": "global"
                    },
                    "HTMLAnjOptionElement": {
                        "location": "global"
                    }
                },
                "return": "Promise<HTMLAnjOptionElement>"
            },
            "docs": {
                "text": "Reset the list",
                "tags": []
            }
        }
    }; }
    static get elementRef() { return "element"; }
    static get watchers() { return [{
            "propName": "active",
            "methodName": "updateActive"
        }]; }
    static get listeners() { return [{
            "name": "keydown",
            "method": "onKeyAction",
            "target": undefined,
            "capture": false,
            "passive": false
        }, {
            "name": "anjContentChange",
            "method": "onOptionsChanged",
            "target": undefined,
            "capture": false,
            "passive": false
        }]; }
}
