/**
 * @license
 * Copyright 2023 Tyler Technologies, Inc. 
 * License: Apache-2.0
 */
import { debounce, getEventPath } from '@tylertech/forge-core';
import { EXPANSION_PANEL_CONSTANTS } from './expansion-panel-constants';
export class ExpansionPanelFoundation {
    constructor(_adapter) {
        this._adapter = _adapter;
        this._open = false;
        this._useAnimations = true;
        this._orientation = EXPANSION_PANEL_CONSTANTS.strings.ORIENTATION_VERTICAL;
        this._isInitialized = false;
        this._clickListener = debounce((evt) => this._onClick(evt), EXPANSION_PANEL_CONSTANTS.numbers.CLICK_DEBOUNCE_THRESHOLD, true);
        this._keydownListener = (evt) => this._onKeydown(evt);
        this._headerSlotChangeListener = (evt) => this._onHeaderSlotChanged(evt);
    }
    initialize() {
        this.connect();
        this._adapter.initialize(this._open, this._orientation);
        this._isInitialized = true;
    }
    connect() {
        this._adapter.registerHeaderSlotListener(this._headerSlotChangeListener);
        this._adapter.registerClickListener(this._clickListener);
        this._adapter.registerKeydownListener(this._keydownListener);
    }
    disconnect() {
        this._adapter.deregisterHeaderSlotListener(this._headerSlotChangeListener);
        this._adapter.deregisterClickListener(this._clickListener);
        this._adapter.deregisterKeydownListener(this._keydownListener);
    }
    setOpenImmediate(open) {
        if (open) {
            this._openPanel(false);
        }
        else {
            this._closePanel(false);
        }
    }
    _applyOpen(value) {
        if (!this._isInitialized) {
            this._open = value;
            return;
        }
        if (value) {
            if (this._openCallback) {
                Promise.resolve(this._openCallback())
                    .then(() => {
                    this._open = value;
                    this._openPanel(this._useAnimations);
                })
                    .catch(() => { });
            }
            else {
                this._open = value;
                this._openPanel(this._useAnimations);
            }
        }
        else {
            if (this._closeCallback) {
                Promise.resolve(this._closeCallback())
                    .then(() => {
                    this._open = value;
                    this._closePanel(this._useAnimations);
                })
                    .catch(() => { });
            }
            else {
                this._open = value;
                this._closePanel(this._useAnimations);
            }
        }
    }
    /** Controls the open state of the panel. */
    get open() {
        return this._open;
    }
    set open(value) {
        value = Boolean(value);
        if (this._open !== value) {
            this._applyOpen(value);
        }
    }
    get openCallback() {
        return this._openCallback;
    }
    set openCallback(callback) {
        this._openCallback = callback;
    }
    get closeCallback() {
        return this._closeCallback;
    }
    set closeCallback(callback) {
        this._closeCallback = callback;
    }
    get orientation() {
        return this._orientation;
    }
    set orientation(value) {
        this._orientation = value;
    }
    get useAnimations() {
        return this._useAnimations;
    }
    set useAnimations(value) {
        if (this._useAnimations !== !!value) {
            this._useAnimations = !!value;
            this._adapter.setHostAttribute(EXPANSION_PANEL_CONSTANTS.attributes.USE_ANIMATIONS, `${this._useAnimations}`);
        }
    }
    /**
     * Handles click events on the header element.
     * @param {MouseEvent} evt The click event.
     */
    _onClick(evt) {
        if (getEventPath(evt).find(p => p.nodeType === 1 && (p.hasAttribute(EXPANSION_PANEL_CONSTANTS.attributes.IGNORE) || p.hasAttribute(EXPANSION_PANEL_CONSTANTS.attributes.IGNORE_ALT)))) {
            return;
        }
        evt.stopPropagation();
        this._toggle();
        this._emitEvent();
    }
    /**
     * Handles keydown events on the header.
     * @param {KeyboardEvent} evt The keydown event
     */
    _onKeydown(evt) {
        if (evt.key === ' ' || evt.key === 'Enter') {
            evt.stopPropagation();
            evt.preventDefault();
            this._toggle();
            this._emitEvent();
        }
    }
    _emitEvent() {
        this._adapter.emitHostEvent(EXPANSION_PANEL_CONSTANTS.events.TOGGLE, this._open);
    }
    _toggle() {
        this.open = !this.open;
    }
    _openPanel(animate) {
        this._adapter.setHostAttribute(EXPANSION_PANEL_CONSTANTS.attributes.OPEN, '');
        this._adapter.setOpenState(true, this._orientation, animate);
    }
    _closePanel(animate) {
        this._adapter.removeHostAttribute(EXPANSION_PANEL_CONSTANTS.attributes.OPEN);
        this._adapter.setOpenState(false, this._orientation, animate);
    }
    _onHeaderSlotChanged(evt) {
        this._adapter.setHeaderVisibility(!!evt.target.assignedNodes().length);
    }
}
