/**
 * @license
 * Copyright 2023 Tyler Technologies, Inc. 
 * License: Apache-2.0
 */
import { CHIP_CONSTANTS } from './chip-constants';
export class ChipFoundation {
    constructor(_adapter) {
        this._adapter = _adapter;
        this._type = CHIP_CONSTANTS.defaults.TYPE;
        this._selected = false;
        this._disabled = false;
        this._invalid = false;
        this._value = null;
        this._dense = false;
        this._emulateFocus = false;
        this._isInitialized = false;
        this._clickListener = evt => this._onClick(evt);
        this._keydownListener = evt => this._onKeydown(evt);
        this._deleteKeydownListener = evt => this._onDeleteKeydown(evt);
        this._buttonFocusListener = evt => this._onButtonFocus(evt);
        this._buttonBlurListener = evt => this._onButtonBlur(evt);
    }
    initialize() {
        this._rippleInstance = this._adapter.initializeRipple();
        this._adapter.addRootListener('click', this._clickListener);
        this._adapter.addRootListener('keydown', this._keydownListener);
        this._adapter.addButtonListener('focus', this._buttonFocusListener);
        this._adapter.addButtonListener('blur', this._buttonBlurListener);
        this._applyState();
        this._isInitialized = true;
    }
    disconnect() {
        this._destroyRipple();
        this._adapter.removeRootListener('click', this._clickListener);
        this._adapter.removeRootListener('keydown', this._keydownListener);
        this._adapter.removeButtonListener('focus', this._buttonFocusListener);
        this._adapter.removeButtonListener('blur', this._buttonBlurListener);
        this._isInitialized = false;
    }
    _destroyRipple() {
        if (this._rippleInstance) {
            this._rippleInstance.destroy();
            this._rippleInstance = undefined;
        }
    }
    _applyState() {
        // Attempt to inherit state from the parent chip-set component
        // Note: this should only inherit properties that need to be the same across the chips within a set
        const chipSetState = this._adapter.getChipSetState();
        if (chipSetState) {
            this._type = chipSetState.type;
            this._disabled = chipSetState.disabled;
            this._dense = chipSetState.dense;
        }
        // Ensure that only non-action chips can be selected
        if (this._type === 'action') {
            this._selected = false;
        }
        this._applyDisabled();
        this._applyType();
        this._applySelected();
        this._applyDense();
        this._applyEmulateFocus();
    }
    _onClick(evt) {
        const target = evt.target;
        const isDeleteButton = target.classList.contains(CHIP_CONSTANTS.classes.DELETE_BUTTON) ||
            target.classList.contains(CHIP_CONSTANTS.classes.DELETE_BUTTON_TOUCH_TARGET);
        if (isDeleteButton) {
            this._handleDeleteInteraction(evt);
        }
        else {
            this._handleSelectInteraction();
        }
    }
    _onKeydown(evt) {
        var _a;
        switch (evt.key) {
            case 'Delete':
            case 'Backspace':
                if (this._type === 'input') {
                    evt.preventDefault();
                    this._emitDeleteEvent();
                }
                break;
            case 'Enter':
            case ' ':
                evt.preventDefault();
                (_a = this._rippleInstance) === null || _a === void 0 ? void 0 : _a.animate();
                this._handleSelectInteraction();
                break;
            case 'ArrowLeft':
                evt.preventDefault();
                this._adapter.tryMoveFocusPrevious();
                break;
            case 'ArrowRight':
                evt.preventDefault();
                this._adapter.tryMoveFocusNext();
                break;
        }
    }
    _onDeleteKeydown(evt) {
        if (evt.key === 'Enter') {
            this._handleDeleteInteraction(evt);
        }
    }
    _onButtonFocus(evt) {
        this._adapter.setHostAttribute('focused');
    }
    _onButtonBlur(evt) {
        this._adapter.removeHostAttribute('focused');
    }
    _handleDeleteInteraction(evt) {
        // The delete event can only be fired when the `input` or `field` type is used
        const target = evt.target;
        const isDeleteButton = target.classList.contains(CHIP_CONSTANTS.classes.DELETE_BUTTON) ||
            target.classList.contains(CHIP_CONSTANTS.classes.DELETE_BUTTON_TOUCH_TARGET);
        if (isDeleteButton) {
            evt.stopPropagation();
            this._emitDeleteEvent();
        }
    }
    _handleSelectInteraction() {
        const wasDefaultPrevented = this._emitSelectEvent();
        const isSelectableType = ['filter', 'choice', 'input'].includes(this._type);
        // We only toggle the selected state for certain types (and if default wasn't prevented on the event)
        if (!wasDefaultPrevented && isSelectableType) {
            this._selected = !this._selected;
            this._applySelected();
        }
    }
    _emitSelectEvent() {
        const selectEventData = {
            selected: !this._selected,
            value: this._value
        };
        return !this._adapter.emitHostEvent(CHIP_CONSTANTS.events.SELECT, selectEventData, true, true);
    }
    _emitDeleteEvent() {
        const deleteEventData = { value: this._value };
        this._adapter.emitHostEvent(CHIP_CONSTANTS.events.DELETE, deleteEventData, true, true);
    }
    _applyType() {
        this._adapter.clearTypeClass();
        switch (this._type) {
            case 'action':
                this._adapter.addRootClass(CHIP_CONSTANTS.classes.ACTION);
                break;
            case 'choice':
                this._adapter.addRootClass(CHIP_CONSTANTS.classes.CHOICE);
                break;
            case 'filter':
                this._adapter.addRootClass(CHIP_CONSTANTS.classes.FILTER);
                break;
            case 'input':
                this._adapter.addRootClass(CHIP_CONSTANTS.classes.INPUT);
                break;
            case 'field':
                this._adapter.addRootClass(CHIP_CONSTANTS.classes.FIELD);
                break;
        }
        this._adapter.setCheckmarkVisibility(this._type === 'filter');
        const showDeleteButton = this._type === 'input' || this._type === 'field';
        this._adapter.setDeleteButtonVisibility(showDeleteButton, this._deleteKeydownListener);
        this._adapter.setLeadingSlotVisibility(!this._selected);
        this._adapter.setHostAttribute(CHIP_CONSTANTS.attributes.TYPE, this._type);
    }
    _applySelected() {
        this._adapter.setSelected(this._selected);
        // If using the filter type, we need to hide the leading slot to ensure that
        // the checkmark shows in place of any leading elements
        if (this._type === 'filter') {
            this._adapter.setLeadingSlotVisibility(!this._selected);
        }
        this._adapter.toggleHostAttribute(CHIP_CONSTANTS.attributes.SELECTED, this._selected);
    }
    _applyDisabled() {
        this._adapter.setDisabled(this._disabled);
        this._adapter.toggleHostAttribute(CHIP_CONSTANTS.attributes.DISABLED, this._disabled);
    }
    _applyDense() {
        this._adapter.setDense(this._dense);
        this._adapter.toggleHostAttribute(CHIP_CONSTANTS.attributes.DISABLED, this._disabled);
    }
    _applyEmulateFocus() {
        this._adapter.toggleHostAttribute(CHIP_CONSTANTS.attributes.EMULATE_FOCUS, this._emulateFocus);
        this._adapter.setEmulatedFocus(this._emulateFocus);
    }
    get type() {
        return this._type;
    }
    set type(value) {
        if (this._type !== value) {
            this._type = value;
            if (this._isInitialized) {
                const isValidType = ['action', 'choice', 'filter', 'input', 'field'].includes(this._type);
                if (!isValidType) {
                    this._type = 'action';
                }
                if (this._type === 'action') {
                    this._selected = false;
                    this._applySelected();
                }
                this._applyType();
            }
        }
    }
    get selected() {
        return this._selected;
    }
    set selected(value) {
        if (this._selected !== value) {
            this._selected = value;
            if (this._isInitialized) {
                if (this._type === 'action') {
                    this._selected = false;
                }
                this._applySelected();
            }
        }
    }
    get disabled() {
        return this._disabled;
    }
    set disabled(value) {
        if (this._disabled !== value) {
            this._disabled = value;
            if (this._isInitialized) {
                this._applyDisabled();
            }
        }
    }
    get invalid() {
        return this._invalid;
    }
    set invalid(val) {
        if (this._invalid === val) {
            return;
        }
        this._invalid = val;
        if (val) {
            this._adapter.setHostAttribute(CHIP_CONSTANTS.attributes.INVALID, '');
            this._adapter.addRootClass(CHIP_CONSTANTS.classes.INVALID);
        }
        else {
            this._adapter.removeHostAttribute(CHIP_CONSTANTS.attributes.INVALID);
            this._adapter.removeRootClass(CHIP_CONSTANTS.classes.INVALID);
        }
    }
    get value() {
        return this._value;
    }
    set value(value) {
        this._value = value;
    }
    get dense() {
        return this._dense;
    }
    set dense(value) {
        if (this._dense !== value) {
            this._dense = value;
            if (this._isInitialized) {
                this._applyDense();
            }
        }
    }
    get emulateFocus() {
        return this._emulateFocus;
    }
    set emulateFocus(value) {
        if (this._emulateFocus !== value) {
            this._emulateFocus = value;
            if (this._isInitialized) {
                this._applyEmulateFocus();
            }
        }
    }
    setFocus() {
        this._adapter.setFocus();
    }
    tryFocusDelete() {
        if (this._type === 'input') {
            this._adapter.tryFocusDelete();
            return;
        }
        this.setFocus();
    }
}
