/*!
 * (C) Ionic http://ionicframework.com - MIT License
 */
import { Host, h, writeTask } from "@stencil/core";
import { findIonContent, getScrollElement, printIonContentErrorMsg } from "../../utils/content/index";
import { inheritAriaAttributes } from "../../utils/helpers";
import { hostContext } from "../../utils/theme";
import { config } from "../../global/config";
import { getIonTheme } from "../../global/ionic-global";
import { cloneElement, createHeaderIndex, handleContentScroll, handleHeaderFade, handleToolbarIntersection, setHeaderActive, setToolbarBackgroundOpacity, getRoleType, } from "./header.utils";
/**
 * @virtualProp {"ios" | "md"} mode - The mode determines the platform behaviors of the component.
 * @virtualProp {"ios" | "md" | "ionic"} theme - The theme determines the visual appearance of the component.
 */
export class Header {
    constructor() {
        this.inheritedAttributes = {};
        /**
         * If `true`, the header will have a line at the bottom.
         * TODO(ROU-10855): add support for this prop on ios/md themes
         */
        this.divider = false;
        /**
         * If `true`, the header will be translucent.
         * Only applies when the theme is `"ios"` or `"ionic"` and the device supports
         * [`backdrop-filter`](https://developer.mozilla.org/en-US/docs/Web/CSS/backdrop-filter#Browser_compatibility).
         *
         * Note: In order to scroll content behind the header, the `fullscreen`
         * attribute needs to be set on the content.
         */
        this.translucent = false;
        this.setupFadeHeader = async (contentEl, condenseHeader) => {
            const scrollEl = (this.scrollEl = await getScrollElement(contentEl));
            /**
             * Handle fading of toolbars on scroll
             */
            this.contentScrollCallback = () => {
                handleHeaderFade(this.scrollEl, this.el, condenseHeader);
            };
            scrollEl.addEventListener('scroll', this.contentScrollCallback);
            handleHeaderFade(this.scrollEl, this.el, condenseHeader);
        };
    }
    componentWillLoad() {
        this.inheritedAttributes = inheritAriaAttributes(this.el);
    }
    componentDidLoad() {
        this.checkCollapsibleHeader();
    }
    componentDidUpdate() {
        this.checkCollapsibleHeader();
    }
    disconnectedCallback() {
        this.destroyCollapsibleHeader();
    }
    async checkCollapsibleHeader() {
        const theme = getIonTheme(this);
        if (theme !== 'ios') {
            return;
        }
        const { collapse } = this;
        const hasCondense = collapse === 'condense';
        const hasFade = collapse === 'fade';
        this.destroyCollapsibleHeader();
        const appRootSelector = config.get('appRootSelector', 'ion-app');
        if (hasCondense) {
            const pageEl = this.el.closest(`${appRootSelector},ion-page,.ion-page,page-inner`);
            const contentEl = pageEl ? findIonContent(pageEl) : null;
            // Cloned elements are always needed in iOS transition
            writeTask(() => {
                const title = cloneElement('ion-title');
                title.size = 'large';
                cloneElement('ion-back-button');
            });
            await this.setupCondenseHeader(contentEl, pageEl);
        }
        else if (hasFade) {
            const pageEl = this.el.closest(`${appRootSelector},ion-page,.ion-page,page-inner`);
            const contentEl = pageEl ? findIonContent(pageEl) : null;
            if (!contentEl) {
                printIonContentErrorMsg(this.el);
                return;
            }
            const condenseHeader = contentEl.querySelector('ion-header[collapse="condense"]');
            await this.setupFadeHeader(contentEl, condenseHeader);
        }
    }
    destroyCollapsibleHeader() {
        if (this.intersectionObserver) {
            this.intersectionObserver.disconnect();
            this.intersectionObserver = undefined;
        }
        if (this.scrollEl && this.contentScrollCallback) {
            this.scrollEl.removeEventListener('scroll', this.contentScrollCallback);
            this.contentScrollCallback = undefined;
        }
        if (this.collapsibleMainHeader) {
            this.collapsibleMainHeader.classList.remove('header-collapse-main');
            this.collapsibleMainHeader = undefined;
        }
    }
    async setupCondenseHeader(contentEl, pageEl) {
        if (!contentEl || !pageEl) {
            printIonContentErrorMsg(this.el);
            return;
        }
        if (typeof IntersectionObserver === 'undefined') {
            return;
        }
        this.scrollEl = await getScrollElement(contentEl);
        const headers = pageEl.querySelectorAll('ion-header');
        this.collapsibleMainHeader = Array.from(headers).find((header) => header.collapse !== 'condense');
        if (!this.collapsibleMainHeader) {
            return;
        }
        const mainHeaderIndex = createHeaderIndex(this.collapsibleMainHeader);
        const scrollHeaderIndex = createHeaderIndex(this.el);
        if (!mainHeaderIndex || !scrollHeaderIndex) {
            return;
        }
        setHeaderActive(mainHeaderIndex, false);
        setToolbarBackgroundOpacity(mainHeaderIndex.el, 0);
        /**
         * Handle interaction between toolbar collapse and
         * showing/hiding content in the primary ion-header
         * as well as progressively showing/hiding the main header
         * border as the top-most toolbar collapses or expands.
         */
        const toolbarIntersection = (ev) => {
            handleToolbarIntersection(ev, mainHeaderIndex, scrollHeaderIndex, this.scrollEl);
        };
        this.intersectionObserver = new IntersectionObserver(toolbarIntersection, {
            root: contentEl,
            threshold: [0.25, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1],
        });
        this.intersectionObserver.observe(scrollHeaderIndex.toolbars[scrollHeaderIndex.toolbars.length - 1].el);
        /**
         * Handle scaling of large iOS titles and
         * showing/hiding border on last toolbar
         * in primary header
         */
        this.contentScrollCallback = () => {
            handleContentScroll(this.scrollEl, scrollHeaderIndex, contentEl);
        };
        this.scrollEl.addEventListener('scroll', this.contentScrollCallback);
        writeTask(() => {
            if (this.collapsibleMainHeader !== undefined) {
                this.collapsibleMainHeader.classList.add('header-collapse-main');
            }
        });
    }
    render() {
        const { translucent, inheritedAttributes, divider } = this;
        const theme = getIonTheme(this);
        const collapse = this.collapse || 'none';
        const isCondensed = collapse === 'condense';
        // banner role must be at top level, so remove role if inside a menu
        const roleType = getRoleType(hostContext('ion-menu', this.el), isCondensed, theme);
        return (h(Host, Object.assign({ key: '658d5746920c349cc9fe85666c7215f2edc3c794', role: roleType, class: {
                [theme]: true,
                // Used internally for styling
                [`header-${theme}`]: true,
                [`header-translucent`]: this.translucent,
                [`header-collapse-${collapse}`]: true,
                [`header-translucent-${theme}`]: this.translucent,
                ['header-divider']: divider,
            } }, inheritedAttributes), theme !== 'md' && translucent && h("div", { key: '4a1470d86e1aac6f8d545fe01e75b4dce665fb70', class: "header-background" }), h("slot", { key: '3b02661242bda5834c4e13e4eb61bf79b53ba33e' })));
    }
    static get is() { return "ion-header"; }
    static get originalStyleUrls() {
        return {
            "ios": ["header.ios.scss"],
            "md": ["header.md.scss"],
            "ionic": ["header.ionic.scss"]
        };
    }
    static get styleUrls() {
        return {
            "ios": ["header.ios.css"],
            "md": ["header.md.css"],
            "ionic": ["header.ionic.css"]
        };
    }
    static get properties() {
        return {
            "collapse": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "'condense' | 'fade'",
                    "resolved": "\"condense\" | \"fade\" | undefined",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Describes the scroll effect that will be applied to the header.\nOnly applies when the theme is `\"ios\"`.\n\nTypically used for [Collapsible Large Titles](https://ionicframework.com/docs/api/title#collapsible-large-titles)"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "collapse"
            },
            "divider": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "If `true`, the header will have a line at the bottom.\nTODO(ROU-10855): add support for this prop on ios/md themes"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "divider",
                "defaultValue": "false"
            },
            "translucent": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "If `true`, the header will be translucent.\nOnly applies when the theme is `\"ios\"` or `\"ionic\"` and the device supports\n[`backdrop-filter`](https://developer.mozilla.org/en-US/docs/Web/CSS/backdrop-filter#Browser_compatibility).\n\nNote: In order to scroll content behind the header, the `fullscreen`\nattribute needs to be set on the content."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "translucent",
                "defaultValue": "false"
            }
        };
    }
    static get elementRef() { return "el"; }
}
