import { MDCList } from "@material/list";
import { strings as listStrings } from "@material/list/constants";
import { h, Host, } from "@stencil/core";
import { ListRenderer } from "./list-renderer";
const { ACTION_EVENT } = listStrings;
/**
 * @exampleComponent limel-example-list-basic
 * @exampleComponent limel-example-list-secondary
 * @exampleComponent limel-example-list-separator
 * @exampleComponent limel-example-list-icons
 * @exampleComponent limel-example-list-badge-icons
 * @exampleComponent limel-example-list-pictures
 * @exampleComponent limel-example-list-selectable
 * @exampleComponent limel-example-list-checkbox-icons
 * @exampleComponent limel-example-list-radio-button-icons
 * @exampleComponent limel-example-list-action
 * @exampleComponent limel-example-list-striped
 * @exampleComponent limel-example-list-badge-icons-with-multiple-lines
 * @exampleComponent limel-example-list-grid
 * @exampleComponent limel-example-list-primary-component
 */
export class List {
    constructor() {
        /**
         * Size of the icons in the list
         */
        this.iconSize = 'small';
        /**
         * By default, lists will display 3 lines of text, and then truncate the rest.
         * Consumers can increase or decrease this number by specifying
         * `maxLinesSecondaryText`. If consumer enters zero or negative
         * numbers we default to 1; and if they type decimals we round up.
         */
        this.maxLinesSecondaryText = 3;
        this.listRenderer = new ListRenderer();
        this.setup = () => {
            this.setupList();
            this.setupListeners();
        };
        this.setupList = () => {
            if (this.mdcList) {
                this.teardown();
                this.mdcList = null;
            }
            const element = this.element.shadowRoot.querySelector('.mdc-deprecated-list');
            if (!element) {
                return;
            }
            this.mdcList = new MDCList(element);
            this.mdcList.hasTypeahead = true;
        };
        this.setupListeners = () => {
            if (!this.mdcList) {
                return;
            }
            this.mdcList.unlisten(ACTION_EVENT, this.handleAction);
            this.selectable = ['selectable', 'radio', 'checkbox'].includes(this.type);
            this.multiple = this.type === 'checkbox';
            if (!this.selectable) {
                return;
            }
            this.mdcList.listen(ACTION_EVENT, this.handleAction);
            this.mdcList.singleSelection = !this.multiple;
        };
        this.teardown = () => {
            var _a, _b;
            (_a = this.mdcList) === null || _a === void 0 ? void 0 : _a.unlisten(ACTION_EVENT, this.handleAction);
            (_b = this.mdcList) === null || _b === void 0 ? void 0 : _b.destroy();
        };
        this.handleAction = (event) => {
            if (!this.multiple) {
                this.handleSingleSelect(event.detail.index);
                return;
            }
            this.handleMultiSelect(event.detail.index);
        };
        this.handleSingleSelect = (index) => {
            const listItems = this.items.filter(this.isListItem);
            if (listItems[index].disabled) {
                return;
            }
            const selectedItem = listItems.find((item) => {
                return !!item.selected;
            });
            let interactedItem;
            if (selectedItem) {
                if (this.type !== 'radio') {
                    this.mdcList.selectedIndex = -1;
                }
                interactedItem = Object.assign(Object.assign({}, selectedItem), { selected: false });
                this.change.emit(interactedItem);
            }
            if (listItems[index] !== selectedItem) {
                interactedItem = Object.assign(Object.assign({}, listItems[index]), { selected: true });
                this.change.emit(interactedItem);
            }
            this.interact.emit(interactedItem);
        };
        this.handleMultiSelect = (index) => {
            const listItems = this.items.filter(this.isListItem);
            if (listItems[index].disabled) {
                return;
            }
            const selectedItems = listItems
                .filter((item, listIndex) => {
                if (listIndex === index) {
                    // This is the item that was selected or deselected,
                    // so we negate its previous selection status.
                    return !item.selected;
                }
                // This is an item that didn't change, so we keep its selection status.
                return item.selected;
            })
                .map((item) => {
                return Object.assign(Object.assign({}, item), { selected: true });
            });
            this.change.emit(selectedItems);
            this.interact.emit(Object.assign({}, selectedItems[index]));
        };
        this.isListItem = (item) => {
            return !('separator' in item);
        };
    }
    connectedCallback() {
        this.setup();
    }
    disconnectedCallback() {
        this.teardown();
    }
    componentDidLoad() {
        this.setup();
        this.triggerIconColorWarning();
    }
    render() {
        var _a;
        this.config = {
            badgeIcons: this.badgeIcons,
            type: this.type,
            iconSize: this.iconSize,
        };
        let maxLinesSecondaryText = +((_a = this.maxLinesSecondaryText) === null || _a === void 0 ? void 0 : _a.toFixed());
        if (this.maxLinesSecondaryText < 1) {
            maxLinesSecondaryText = 1;
        }
        const html = this.listRenderer.render(this.items, this.config);
        return (h(Host, { key: 'cbe0fda77189118ad3515dc3c4ab02c6cd9bc58a', style: {
                '--maxLinesSecondaryText': `${maxLinesSecondaryText}`,
            } }, html));
    }
    handleType() {
        this.setupListeners();
    }
    itemsChanged() {
        if (!this.mdcList) {
            return;
        }
        setTimeout(() => {
            this.setup();
            const listItems = this.items.filter(this.isListItem);
            if (this.multiple) {
                this.mdcList.selectedIndex = listItems
                    .filter((item) => item.selected)
                    .map((item) => listItems.indexOf(item));
            }
            else {
                const selectedIndex = listItems.findIndex((item) => item.selected);
                if (selectedIndex === -1) {
                    this.mdcList.initializeListType();
                }
                else {
                    this.mdcList.selectedIndex = selectedIndex;
                }
            }
        }, 0);
    }
    triggerIconColorWarning() {
        var _a;
        if ((_a = this.items) === null || _a === void 0 ? void 0 : _a.some((item) => 'iconColor' in item)) {
            console.warn("The `iconColor` prop is deprecated, has no visual effect anymore, and will soon be removed! Use the new `Icon` interface, and instead of `iconColor: 'color-name'` write `icon: { name: 'icon-name', color: 'color-name' }`.");
        }
    }
    static get is() { return "limel-list"; }
    static get encapsulation() { return "shadow"; }
    static get delegatesFocus() { return true; }
    static get originalStyleUrls() {
        return {
            "$": ["list.scss"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["list.css"]
        };
    }
    static get properties() {
        return {
            "items": {
                "type": "unknown",
                "mutable": false,
                "complexType": {
                    "original": "Array<ListItem | ListSeparator>",
                    "resolved": "(ListSeparator | ListItem<any>)[]",
                    "references": {
                        "Array": {
                            "location": "global",
                            "id": "global::Array"
                        },
                        "ListItem": {
                            "location": "import",
                            "path": "../list-item/list-item.types",
                            "id": "src/components/list-item/list-item.types.ts::ListItem",
                            "referenceLocation": "ListItem"
                        },
                        "ListSeparator": {
                            "location": "import",
                            "path": "../list-item/list-item.types",
                            "id": "src/components/list-item/list-item.types.ts::ListSeparator",
                            "referenceLocation": "ListSeparator"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "List of items to display"
                },
                "getter": false,
                "setter": false
            },
            "badgeIcons": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Set to `true` if the list should display larger icons with a background"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "badge-icons"
            },
            "iconSize": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "IconSize",
                    "resolved": "\"large\" | \"medium\" | \"small\" | \"x-small\"",
                    "references": {
                        "IconSize": {
                            "location": "import",
                            "path": "../icon/icon.types",
                            "id": "src/components/icon/icon.types.ts::IconSize",
                            "referenceLocation": "IconSize"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Size of the icons in the list"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "icon-size",
                "defaultValue": "'small'"
            },
            "type": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "ListType",
                    "resolved": "\"checkbox\" | \"radio\" | \"selectable\"",
                    "references": {
                        "ListType": {
                            "location": "import",
                            "path": "./list.types",
                            "id": "src/components/list/list.types.ts::ListType",
                            "referenceLocation": "ListType"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "The type of the list, omit to get a regular list. Available types are:\n`selectable`: regular list with single selection.\n`radio`: radio button list with single selection.\n`checkbox`: checkbox list with multiple selection."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "type"
            },
            "maxLinesSecondaryText": {
                "type": "number",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "By default, lists will display 3 lines of text, and then truncate the rest.\nConsumers can increase or decrease this number by specifying\n`maxLinesSecondaryText`. If consumer enters zero or negative\nnumbers we default to 1; and if they type decimals we round up."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "max-lines-secondary-text",
                "defaultValue": "3"
            }
        };
    }
    static get events() {
        return [{
                "method": "change",
                "name": "change",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Fired when a new value has been selected from the list.\nOnly fired if `type` is set to `selectable`, `radio` or `checkbox`."
                },
                "complexType": {
                    "original": "ListItem | ListItem[]",
                    "resolved": "ListItem<any> | ListItem<any>[]",
                    "references": {
                        "ListItem": {
                            "location": "import",
                            "path": "../list-item/list-item.types",
                            "id": "src/components/list-item/list-item.types.ts::ListItem",
                            "referenceLocation": "ListItem"
                        }
                    }
                }
            }, {
                "method": "select",
                "name": "select",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Fired when an action has been selected from the action menu of a list item"
                },
                "complexType": {
                    "original": "ListItem | ListItem[]",
                    "resolved": "ListItem<any> | ListItem<any>[]",
                    "references": {
                        "ListItem": {
                            "location": "import",
                            "path": "../list-item/list-item.types",
                            "id": "src/components/list-item/list-item.types.ts::ListItem",
                            "referenceLocation": "ListItem"
                        }
                    }
                }
            }, {
                "method": "interact",
                "name": "interact",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Fires when a user interacts with an item in the list (e.g., click,\nkeyboard select)."
                },
                "complexType": {
                    "original": "ListItem",
                    "resolved": "ListItem<any>",
                    "references": {
                        "ListItem": {
                            "location": "import",
                            "path": "../list-item/list-item.types",
                            "id": "src/components/list-item/list-item.types.ts::ListItem",
                            "referenceLocation": "ListItem"
                        }
                    }
                }
            }];
    }
    static get elementRef() { return "element"; }
    static get watchers() {
        return [{
                "propName": "type",
                "methodName": "handleType"
            }, {
                "propName": "items",
                "methodName": "itemsChanged"
            }];
    }
}
