/**
 * @license
 * Copyright Tyler Technologies, Inc. 
 * License: Apache-2.0
 */
import { task } from '../../core/utils/event-utils';
import { BASE_BUTTON_CONSTANTS } from './base-button-constants';
export class BaseButtonFoundation {
    constructor(_adapter) {
        this._adapter = _adapter;
        this._type = 'button'; // We default our buttons to the "button" type instead of "submit" as that is more common
        this._disabled = false;
        this._popoverIcon = false;
        this._anchor = false;
        this._href = '';
        this._target = '';
        this._download = '';
        this._rel = '';
        this._dense = false;
        this._clickListener = (evt) => this._onClick(evt);
        this._keydownListener = (evt) => this._onKeydown(evt);
        this._anchorFocusListener = () => this._adapter.focusHost(); // Always ensure our host is focused when the anchor is focused
        this._adapter.addHostListener('keydown', this._keydownListener);
    }
    initialize() {
        this._adapter.initialize();
        if (this._anchor) {
            // When we're in anchor mode, we swap to us an `<a>` internally as the root. Since the `<a>`
            // element is interactive by default, we can remove our click listener since the anchor will
            // take over the default interaction handling
            this._adapter.addAnchorEventListener('focus', this._anchorFocusListener);
        }
        else {
            // When we're in button mode, we need to handle the click event on the host element
            this._adapter.addHostListener('click', this._clickListener);
        }
    }
    /**
     * Handles overriding the the `click()` method on the HTMLElement instance
     */
    click({ animateStateLayer = false } = {}) {
        if (this._disabled) {
            return;
        }
        if (this._anchor) {
            this._adapter.clickAnchor();
        }
        else {
            this._adapter.clickHost();
        }
        if (animateStateLayer) {
            this._adapter.animateStateLayer();
        }
    }
    focus(options) {
        this._adapter.focusHost(options);
        if ((options === null || options === void 0 ? void 0 : options.focusVisible) !== false) {
            this._adapter.forceFocusVisible();
        }
    }
    async _onClick(evt) {
        const isFormType = this._type === 'submit' || this._type === 'reset';
        // Custom elements do not work with the popover* attributes by default so we need to manually
        // manage the popover functionality for now...
        if (!isFormType && this._adapter.hasPopoverTarget()) {
            const isOpen = this._adapter.managePopover();
            // If the popover was opened successfully we can stop here since there is no need to
            // handle any other scenarios
            if (isOpen) {
                return;
            }
        }
        // Wait a cycle to allow the click event to propagate
        await new Promise(resolve => setTimeout(resolve));
        // We allow for our click event to bubble first before we handle it in case the developer
        // wants to prevent the default behavior
        if (evt.defaultPrevented || this._disabled) {
            return;
        }
        // For button types of submit or reset, we need to manually submit or reset the form
        // since the click event doesn't do that for us with custom elements
        if (isFormType) {
            this._adapter.clickFormButton(this._type);
        }
    }
    /**
     * Handle keydown events on the host element to manually trigger click events.
     */
    async _onKeydown(evt) {
        // Handle the special case for the space key (when not an anchor) to avoid
        // scrolling when triggered
        if (evt.key === ' ' && !this._anchor) {
            evt.preventDefault();
            this.click();
            return;
        }
        // Wait a cycle for the keydown event to propagate
        await task();
        if (evt.defaultPrevented || this._disabled) {
            return;
        }
        if (evt.key === 'Enter') {
            if (this._anchor) {
                this._adapter.clickAnchor();
            }
            else {
                this.click();
            }
        }
    }
    _toggleAnchor() {
        if (this._anchor) {
            this._adapter.initializeAnchor();
            this._manageAnchorListeners();
            this.disabled = false; // Anchor elements are always enabled
        }
        else {
            this._adapter.removeAnchor();
            this._manageAnchorListeners();
        }
    }
    _manageAnchorListeners() {
        if (this._anchor) {
            this._adapter.removeHostListener('click', this._clickListener);
            this._adapter.addAnchorEventListener('focus', this._anchorFocusListener);
        }
        else {
            this._adapter.addHostListener('click', this._clickListener);
            this._adapter.removeAnchorEventListener('focus', this._anchorFocusListener);
        }
    }
    get type() {
        return this._type;
    }
    set type(type) {
        if (this._type !== type) {
            this._type = type;
            this._adapter.setHostAttribute(BASE_BUTTON_CONSTANTS.attributes.TYPE, type);
        }
    }
    get disabled() {
        return this._disabled;
    }
    set disabled(value) {
        value = Boolean(value);
        if (this._disabled === value) {
            return;
        }
        // When we're in anchor mode we need to ensure that the anchor is always enabled
        if (this._anchor) {
            value = false;
        }
        this._disabled = value;
        this._adapter.setDisabled(this._disabled);
        this._adapter.toggleHostAttribute(BASE_BUTTON_CONSTANTS.attributes.DISABLED, value);
    }
    get popoverIcon() {
        return this._popoverIcon;
    }
    set popoverIcon(value) {
        value = Boolean(value);
        if (this._popoverIcon !== value) {
            this._popoverIcon = value;
            this._adapter.toggleDefaultPopoverIcon(this._popoverIcon);
            this._adapter.toggleHostAttribute(BASE_BUTTON_CONSTANTS.attributes.POPOVER_ICON, value);
        }
    }
    /**
     * Anchor properties
     */
    get anchor() {
        return this._anchor;
    }
    set anchor(value) {
        value = Boolean(value);
        if (this._anchor !== value) {
            this._anchor = value;
            this._toggleAnchor();
            this._adapter.toggleHostAttribute(BASE_BUTTON_CONSTANTS.attributes.ANCHOR, value);
        }
    }
    get href() {
        return this._href;
    }
    set href(value) {
        value = (value !== null && value !== void 0 ? value : '').trim();
        if (this._href !== value) {
            this._href = value;
            this.anchor = this._href.length > 0;
            if (this._anchor) {
                this._adapter.setAnchorProperty('href', this._href);
            }
            this._adapter.toggleHostAttribute(BASE_BUTTON_CONSTANTS.attributes.HREF, !!this._href, this._href);
        }
    }
    get target() {
        return this._target;
    }
    set target(value) {
        if (this._target !== value) {
            this._target = value !== null && value !== void 0 ? value : '_self';
            this._adapter.setAnchorProperty('target', value);
            this._adapter.toggleHostAttribute(BASE_BUTTON_CONSTANTS.attributes.TARGET, !!this._target, this._target);
        }
    }
    get download() {
        return this._download;
    }
    set download(value) {
        if (this._download !== value) {
            this._download = value;
            this._adapter.setAnchorProperty('download', this._download);
            this._adapter.toggleHostAttribute(BASE_BUTTON_CONSTANTS.attributes.DOWNLOAD, !!this._download, this._download);
        }
    }
    get rel() {
        return this._rel;
    }
    set rel(value) {
        if (this._rel !== value) {
            this._rel = value;
            this._adapter.setAnchorProperty('rel', this._rel);
            this._adapter.toggleHostAttribute(BASE_BUTTON_CONSTANTS.attributes.REL, !!this._rel, this._rel);
        }
    }
    get dense() {
        return this._dense;
    }
    set dense(value) {
        value = Boolean(value);
        if (this._dense !== value) {
            this._dense = value;
            this._adapter.toggleHostAttribute(BASE_BUTTON_CONSTANTS.attributes.DENSE, value);
        }
    }
}
