import { __decorate, __metadata } from "tslib";
import { h, Host, } from "@stencil/core";
import { BEM } from "../../../utils/bem";
import { ListenToConfig } from "../../../utils/config";
import { raf, rIC, transitionEndAsync } from "../../../utils/helpers";
import { Logger } from "../../../utils/log";
export class ListItem {
    constructor() {
        this.accordionOpen = false;
        this.animated = true;
        this.state = 1 /* AccordionState.Collapsed */;
        /**
         * PUBLIC PROPERTY API
         * ------------------------------------------------------
         */
        /**
         * If `true` the list item can be hovered
         */
        this.disabled = false;
        /**
         * If `true` the list item shows that it is clickable
         */
        this.clickable = false;
        /**
         * If `true` the list item has a selected theme
         */
        this.selected = false;
        /**
         * If `true` the list item can be used as a accordion
         */
        this.accordion = false;
        /**
         * If `true` the list item can be used as an accordion inside another accordion
         */
        this.subAccordionItem = false;
        /**
         * Specifies the URL of the page the link goes to
         */
        this.href = '';
        /**
         * Specifies where to open the linked document
         */
        this.target = '_self';
        /**
         * LISTENERS
         * ------------------------------------------------------
         */
        this.accordionChanged = (ev) => {
            const { detail } = ev;
            if (detail !== this.accordionOpen) {
                this.accordionOpen = detail;
                this.updateState();
            }
        };
        /**
         * PRIVATE METHODS
         * ------------------------------------------------------
         */
        this.addEventListenerAccordionChange = () => {
            const accordionHeadEl = this.el.querySelector(ListItem.selectors.accordionHead);
            if (accordionHeadEl) {
                accordionHeadEl.addEventListener('balAccordionChange', this.accordionChanged);
                this.accordionOpen = accordionHeadEl.accordionOpen;
                this.updateState(true);
            }
        };
        this.removeEventListenerAccordionChange = () => {
            const accordionHeadEl = this.el.querySelector(ListItem.selectors.accordionHead);
            if (accordionHeadEl) {
                accordionHeadEl.removeEventListener('balAccordionChange', this.accordionChanged);
            }
        };
        this.updateHead = () => {
            const headEl = this.el.querySelector('bal-list-item-accordion-head');
            if (headEl) {
                headEl.accordionOpen = this.accordionOpen;
            }
        };
        this.updateState = (initialUpdate = false) => {
            if (this.accordionOpen) {
                this.expandAccordion(initialUpdate);
            }
            else {
                this.collapseAccordion(initialUpdate);
            }
        };
        this.expandAccordion = (initialUpdate = false) => {
            const contentEl = this.el.querySelector(ListItem.selectors.accordionBody);
            const contentElWrapper = this.el.querySelector(ListItem.selectors.accordionBodyWrapper);
            if (initialUpdate || contentEl === null || contentElWrapper === null) {
                this.state = 4 /* AccordionState.Expanded */;
                return;
            }
            if (this.state === 4 /* AccordionState.Expanded */) {
                return;
            }
            if (this.currentRaf !== undefined) {
                cancelAnimationFrame(this.currentRaf);
            }
            const parentListEl = this.el.closest('bal-list');
            if (parentListEl && parentListEl.accordionOneLevel) {
                const items = Array.from(parentListEl.querySelectorAll('bal-list-item')).filter(el => el !== this.el);
                items.forEach(item => item.dismiss(true));
            }
            if (this.shouldAnimate()) {
                raf(() => {
                    this.state = 8 /* AccordionState.Expanding */;
                    this.currentRaf = raf(async () => {
                        const contentHeight = contentElWrapper.offsetHeight;
                        const waitForTransition = transitionEndAsync(contentEl, 300);
                        contentEl.style.setProperty('max-height', `${contentHeight}px`);
                        this.balWillAnimate.emit(this.accordionOpen);
                        await waitForTransition;
                        this.state = 4 /* AccordionState.Expanded */;
                        contentEl.style.removeProperty('max-height');
                        this.balDidAnimate.emit(this.accordionOpen);
                    });
                });
            }
            else {
                this.balWillAnimate.emit(this.accordionOpen);
                this.state = 4 /* AccordionState.Expanded */;
                this.balDidAnimate.emit(this.accordionOpen);
            }
        };
        this.collapseAccordion = (initialUpdate = false, ignoreNested = false) => {
            const contentEl = this.el.querySelector(ListItem.selectors.accordionBody);
            if (initialUpdate || contentEl === null) {
                this.state = 1 /* AccordionState.Collapsed */;
                return;
            }
            if (this.state === 1 /* AccordionState.Collapsed */) {
                return;
            }
            if (this.currentRaf !== undefined) {
                cancelAnimationFrame(this.currentRaf);
            }
            if (!ignoreNested) {
                const parentListEl = this.el.closest('bal-list');
                if (parentListEl && parentListEl.accordionOneLevel) {
                    const items = Array.from(this.el.querySelectorAll('bal-list-item')).filter(el => el !== this.el);
                    items.forEach(item => item.dismiss(true));
                }
            }
            if (this.shouldAnimate()) {
                this.currentRaf = raf(async () => {
                    const contentHeight = contentEl.offsetHeight;
                    contentEl.style.setProperty('max-height', `${contentHeight}px`);
                    raf(async () => {
                        const waitForTransition = transitionEndAsync(contentEl, 300);
                        this.state = 2 /* AccordionState.Collapsing */;
                        this.balWillAnimate.emit(this.accordionOpen);
                        await waitForTransition;
                        this.state = 1 /* AccordionState.Collapsed */;
                        contentEl.style.removeProperty('max-height');
                        this.balDidAnimate.emit(this.accordionOpen);
                    });
                });
            }
            else {
                this.balWillAnimate.emit(this.accordionOpen);
                this.state = 1 /* AccordionState.Collapsed */;
                this.balDidAnimate.emit(this.accordionOpen);
            }
        };
        this.shouldAnimate = () => {
            if (typeof window === 'undefined') {
                return false;
            }
            return this.animated;
        };
        /**
         * EVENT BINDING
         * ------------------------------------------------------
         */
        this.onClickTrigger = (ev) => {
            const accordionBodyEl = this.el.querySelector(ListItem.selectors.accordionBody);
            if (accordionBodyEl) {
                if (!accordionBodyEl.contains(ev.target)) {
                    this.balNavigate.emit(ev);
                }
            }
            else {
                this.balNavigate.emit(ev);
            }
        };
    }
    createLogger(log) {
        this.log = log;
    }
    /**
     * LIFECYCLE
     * ------------------------------------------------------
     */
    connectedCallback() {
        if (this.accordion) {
            this.addEventListenerAccordionChange();
        }
    }
    componentDidLoad() {
        if (this.accordion) {
            rIC(() => {
                this.addEventListenerAccordionChange();
            });
        }
    }
    disconnectedCallback() {
        this.removeEventListenerAccordionChange();
    }
    /**
     * @internal define config for the component
     */
    async configChanged(state) {
        this.animated = state.animated;
    }
    /**
     * PUBLIC METHODS
     * ------------------------------------------------------
     */
    /**
     * Opens the accordion
     */
    async present() {
        if (this.accordion && this.accordionOpen === false) {
            this.accordionOpen = true;
            this.updateHead();
            this.expandAccordion();
        }
    }
    /**
     * Closes the accordion
     */
    async dismiss(ignoreNested = false) {
        if (this.accordion && this.accordionOpen === true) {
            this.accordionOpen = false;
            this.updateHead();
            this.collapseAccordion(false, ignoreNested);
        }
    }
    /**
     * Triggers the accordion
     */
    async toggle() {
        if (this.accordion) {
            if (this.accordionOpen) {
                this.dismiss();
            }
            else {
                this.present();
            }
        }
    }
    /**
     * RENDER
     * ------------------------------------------------------
     */
    render() {
        const item = BEM.block('list').element('item');
        const trigger = item.element('trigger');
        const basicClasses = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, item.class()), item.modifier('disabled').class(this.disabled)), item.modifier('selected').class(this.selected)), item.modifier('animated').class(this.animated)), item.modifier('accordion').class(this.accordion)), item.modifier('sub-accordion').class(this.subAccordionItem)), item.modifier('active').class(this.accordionOpen)), item.modifier('expanding').class(this.state === 8 /* AccordionState.Expanding */)), item.modifier('expanded').class(this.state === 4 /* AccordionState.Expanded */)), item.modifier('collapsing').class(this.state === 2 /* AccordionState.Collapsing */)), item.modifier('collapsed').class(this.state === 1 /* AccordionState.Collapsed */)), item.modifier('clickable').class(!this.disabled && (this.clickable || this.href.length > 0 || this.accordion)));
        if (this.href.length > 0 && !this.disabled) {
            return (h(Host, { role: "listitem", class: Object.assign({}, basicClasses) }, h("a", { class: Object.assign({}, trigger.class()), rel: this.rel, href: this.href, target: this.target, download: this.download, onClick: (ev) => this.onClickTrigger(ev) }, h("slot", null))));
        }
        if (this.clickable) {
            return (h(Host, { role: "listitem", class: Object.assign({}, basicClasses) }, h("button", { class: Object.assign({}, trigger.class()), disabled: this.disabled, onClick: (ev) => this.onClickTrigger(ev) }, h("slot", null))));
        }
        if (this.accordion) {
            return (h(Host, { role: "listitem", class: Object.assign({}, basicClasses), onClick: (ev) => this.onClickTrigger(ev) }, h("div", { class: Object.assign({}, trigger.class()) }, h("slot", null))));
        }
        return (h(Host, { role: "listitem", class: Object.assign({}, basicClasses) }, h("div", { class: Object.assign({}, trigger.class()) }, h("slot", null))));
    }
    static get is() { return "bal-list-item"; }
    static get properties() {
        return {
            "disabled": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "If `true` the list item can be hovered"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "disabled",
                "defaultValue": "false"
            },
            "clickable": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "If `true` the list item shows that it is clickable"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "clickable",
                "defaultValue": "false"
            },
            "selected": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "If `true` the list item has a selected theme"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "selected",
                "defaultValue": "false"
            },
            "accordion": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "If `true` the list item can be used as a accordion"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "accordion",
                "defaultValue": "false"
            },
            "subAccordionItem": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "If `true` the list item can be used as an accordion inside another accordion"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "sub-accordion-item",
                "defaultValue": "false"
            },
            "href": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Specifies the URL of the page the link goes to"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "href",
                "defaultValue": "''"
            },
            "rel": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string | undefined",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Specifies the relationship of the target object to the link object.\nThe value is a space-separated list of [link types](https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types)."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "rel"
            },
            "target": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "BalProps.BalListItemTarget",
                    "resolved": "\" _parent\" | \"_blank\" | \"_self\" | \"_top\"",
                    "references": {
                        "BalProps": {
                            "location": "global",
                            "id": "global::BalProps"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Specifies where to open the linked document"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "target",
                "defaultValue": "'_self'"
            },
            "download": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "This attribute instructs browsers to download a URL instead of navigating to\nit, so the user will be prompted to save it as a local file. If the attribute\nhas a value, it is used as the pre-filled file name in the Save prompt\n(the user can still change the file name if they want)."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "download"
            }
        };
    }
    static get states() {
        return {
            "state": {}
        };
    }
    static get events() {
        return [{
                "method": "balNavigate",
                "name": "balNavigate",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when the link element has clicked"
                },
                "complexType": {
                    "original": "BalEvents.BalListItemNavigateDetail",
                    "resolved": "MouseEvent",
                    "references": {
                        "BalEvents": {
                            "location": "global",
                            "id": "global::BalEvents"
                        }
                    }
                }
            }, {
                "method": "balGroupStateChanged",
                "name": "balGroupStateChanged",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when the state of the group is changing"
                },
                "complexType": {
                    "original": "BalEvents.BalListItemGroupStateChangedDetail",
                    "resolved": "MouseEvent",
                    "references": {
                        "BalEvents": {
                            "location": "global",
                            "id": "global::BalEvents"
                        }
                    }
                }
            }, {
                "method": "balWillAnimate",
                "name": "balWillAnimate",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted before the animation starts"
                },
                "complexType": {
                    "original": "BalEvents.BalListItemWillAnimateDetail",
                    "resolved": "boolean",
                    "references": {
                        "BalEvents": {
                            "location": "global",
                            "id": "global::BalEvents"
                        }
                    }
                }
            }, {
                "method": "balDidAnimate",
                "name": "balDidAnimate",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted after the animation has finished"
                },
                "complexType": {
                    "original": "BalEvents.BalListItemDidAnimateDetail",
                    "resolved": "boolean",
                    "references": {
                        "BalEvents": {
                            "location": "global",
                            "id": "global::BalEvents"
                        }
                    }
                }
            }];
    }
    static get methods() {
        return {
            "configChanged": {
                "complexType": {
                    "signature": "(state: BalConfigState) => Promise<void>",
                    "parameters": [{
                            "name": "state",
                            "type": "BalConfigState",
                            "docs": ""
                        }],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        },
                        "BalConfigState": {
                            "location": "import",
                            "path": "../../../utils/config",
                            "id": "src/utils/config/index.ts::BalConfigState"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "",
                    "tags": [{
                            "name": "internal",
                            "text": "define config for the component"
                        }]
                }
            },
            "present": {
                "complexType": {
                    "signature": "() => Promise<void>",
                    "parameters": [],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "Opens the accordion",
                    "tags": []
                }
            },
            "dismiss": {
                "complexType": {
                    "signature": "(ignoreNested?: boolean) => Promise<void>",
                    "parameters": [{
                            "name": "ignoreNested",
                            "type": "boolean",
                            "docs": ""
                        }],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "Closes the accordion",
                    "tags": []
                }
            },
            "toggle": {
                "complexType": {
                    "signature": "() => Promise<void>",
                    "parameters": [],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "Triggers the accordion",
                    "tags": []
                }
            }
        };
    }
    static get elementRef() { return "el"; }
}
ListItem.selectors = {
    accordionHead: '.bal-list__item__trigger > bal-list-item-accordion-head',
    accordionBody: '.bal-list__item__trigger > bal-list-item-accordion-body',
    accordionBodyWrapper: '.bal-list__item__trigger > .bal-list__item__accordion-body > .bal-list__item__accordion-body__content',
};
__decorate([
    Logger('bal-list-item'),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Function]),
    __metadata("design:returntype", void 0)
], ListItem.prototype, "createLogger", null);
__decorate([
    ListenToConfig(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], ListItem.prototype, "configChanged", null);
