/**
 * @license
 * Copyright Tyler Technologies, Inc. 
 * License: Apache-2.0
 */
import { CHIP_CONSTANTS } from './chip-constants';
export class ChipCore {
    constructor(_adapter) {
        this._adapter = _adapter;
        this._type = CHIP_CONSTANTS.defaults.TYPE;
        this._selected = false;
        this._invalid = false;
        this._disabled = false;
        this._dense = false;
        this._theme = CHIP_CONSTANTS.defaults.THEME;
        this._clickListener = this._onClick.bind(this);
        this._keydownListener = this._onKeydown.bind(this);
    }
    initialize() {
        this._attachListeners();
        this._tryInheritChipSetState();
    }
    focus(options) {
        this._adapter.focusTrigger(options);
    }
    focusRemoveButton() {
        this._adapter.removeButtonElement?.focus();
    }
    click() {
        this._adapter.clickTrigger();
    }
    _attachListeners() {
        this._adapter.addRootListener('click', this._clickListener);
        this._adapter.addRootListener('keydown', this._keydownListener);
    }
    _detachListeners() {
        this._adapter.removeRootListener('click', this._clickListener);
        this._adapter.removeRootListener('keydown', this._keydownListener);
    }
    _tryInheritChipSetState() {
        // 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) {
            if (chipSetState.type !== undefined) {
                this.type = chipSetState.type;
            }
            if (chipSetState.disabled !== undefined) {
                this.disabled = chipSetState.disabled;
            }
            if (chipSetState.dense !== undefined) {
                this.dense = chipSetState.dense;
            }
        }
    }
    _onClick(evt) {
        if (this._isRemoveButton(evt)) {
            evt.stopImmediatePropagation();
            this._dispatchDeleteEvent();
        }
        else {
            this._handleSelectInteraction();
        }
    }
    _onKeydown(evt) {
        switch (evt.key) {
            case 'Delete':
            case 'Backspace':
                if (this._type === 'input') {
                    evt.preventDefault();
                    this._dispatchDeleteEvent();
                }
                break;
            case 'Enter':
            case ' ':
                evt.preventDefault();
                if (this._isRemoveButton(evt)) {
                    evt.stopImmediatePropagation();
                    if (evt.key === 'Enter') {
                        this._adapter.clickRemoveButton();
                    }
                }
                else {
                    this.click();
                    if (this._adapter.isAnchor) {
                        this._adapter.animateStateLayer();
                    }
                }
                break;
            case 'ArrowLeft':
            case 'ArrowRight':
                this._tryNavigate(evt);
                break;
            case 'Tab':
                if (this._type === 'input' && this._isRemoveButton(evt)) {
                    this._tryNavigate(evt);
                }
                break;
        }
    }
    _tryNavigate(evt) {
        if (this._type === 'input') {
            const isRemoveButtonFocused = !!this._adapter.removeButtonElement?.matches(':focus');
            if (isRemoveButtonFocused) {
                evt.stopPropagation();
                evt.preventDefault();
                if (evt.key === 'ArrowLeft') {
                    this._adapter.focusTrigger();
                    return;
                }
            }
            else if (evt.key === 'ArrowRight') {
                this._adapter.tryFocusRemoveButton();
                return;
            }
        }
        const detail = {
            direction: evt.key === 'ArrowRight' || evt.key === 'Tab' ? 'next' : 'previous'
        };
        this._adapter.dispatchHostEvent(new CustomEvent(CHIP_CONSTANTS.events.NAVIGATE, { bubbles: true, detail }));
    }
    _isRemoveButton(evt) {
        return !!this._adapter.removeButtonElement && evt.composedPath().includes(this._adapter.removeButtonElement);
    }
    _handleSelectInteraction() {
        const originalSelected = this._selected;
        this._selected = !this._selected;
        const wasDefaultPrevented = this._dispatchSelectEvent();
        this._selected = originalSelected;
        const isSelectableType = ['filter', 'choice', 'input'].includes(this._type);
        if (!wasDefaultPrevented && isSelectableType) {
            this._selected = !this._selected;
            this._applySelected();
        }
    }
    _dispatchSelectEvent() {
        const detail = {
            selected: this._selected,
            value: this._value
        };
        const event = new CustomEvent(CHIP_CONSTANTS.events.SELECT, { detail, bubbles: true, cancelable: true });
        this._adapter.dispatchHostEvent(event);
        return event.defaultPrevented;
    }
    _dispatchDeleteEvent() {
        const detail = { value: this._value };
        this._adapter.dispatchHostEvent(new CustomEvent(CHIP_CONSTANTS.events.DELETE, { detail, bubbles: true }));
    }
    _applyType() {
        const showDeleteButton = this._type === 'input' || this._type === 'field';
        this._adapter.setDeleteButtonVisibility(showDeleteButton);
        this._adapter.setCheckmarkVisibility(this._type === 'filter');
        this._adapter.setStartSlotVisibility(!this._selected);
        this._adapter.toggleFieldVariant(this._type !== 'field');
        this._applySelected();
        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.setStartSlotVisibility(!this._selected);
        }
        this._adapter.toggleHostAttribute(CHIP_CONSTANTS.attributes.SELECTED, this._selected);
    }
    get type() {
        return this._type;
    }
    set type(value) {
        if (this._type !== value) {
            this._type = value;
            const isValidType = ['action', 'choice', 'filter', 'input', 'field'].includes(this._type);
            if (!isValidType) {
                this._type = 'action';
            }
            this._applyType();
        }
    }
    get value() {
        return this._value;
    }
    set value(value) {
        if (this._value !== value) {
            this._value = value;
            this._adapter.setHostAttribute(CHIP_CONSTANTS.attributes.VALUE, String(this._value));
        }
    }
    get selected() {
        return this._selected;
    }
    set selected(value) {
        value = Boolean(value);
        if (this._selected !== value) {
            this._selected = value;
            this._applySelected();
        }
    }
    get invalid() {
        return this._invalid;
    }
    set invalid(value) {
        value = Boolean(value);
        if (this._invalid !== value) {
            this._invalid = value;
            this._adapter.toggleHostAttribute(CHIP_CONSTANTS.attributes.INVALID, value);
        }
    }
    get disabled() {
        return this._disabled;
    }
    set disabled(value) {
        value = Boolean(value);
        if (this._disabled !== value) {
            this._disabled = value;
            this._adapter.setDisabled(this._disabled);
            if (this._adapter.isConnected) {
                if (this._disabled) {
                    this._detachListeners();
                }
                else {
                    this._attachListeners();
                }
            }
            this._adapter.toggleHostAttribute(CHIP_CONSTANTS.attributes.DISABLED, this._disabled);
        }
    }
    get dense() {
        return this._dense;
    }
    set dense(value) {
        value = Boolean(value);
        if (this._dense !== value) {
            this._dense = value;
            this._adapter.toggleHostAttribute(CHIP_CONSTANTS.attributes.DENSE, this._dense);
        }
    }
    get theme() {
        return this._theme;
    }
    set theme(value) {
        if (this._theme !== value) {
            this._theme = value ?? CHIP_CONSTANTS.defaults.THEME;
            this._adapter.setHostAttribute(CHIP_CONSTANTS.attributes.THEME, this._theme);
        }
    }
    get href() {
        return this._href;
    }
    set href(value) {
        if (this._href !== value) {
            this._href = value;
            const hasHref = !!this._href?.trim();
            this._adapter.setAnchor(hasHref);
            if (hasHref && this._disabled) {
                this._adapter.setDisabled(false);
            }
            this._adapter.toggleHostAttribute(CHIP_CONSTANTS.attributes.HREF, hasHref, this._href);
        }
    }
    get target() {
        return this._target;
    }
    set target(value) {
        if (this._target !== value) {
            this._target = value;
            this._adapter.setAnchorProperty('target', value);
            this._adapter.toggleHostAttribute(CHIP_CONSTANTS.attributes.TARGET, !!this._target?.trim(), this._target);
        }
    }
    get download() {
        return this._download;
    }
    set download(value) {
        if (this._download !== value) {
            this._download = value;
            this._adapter.setAnchorProperty('download', value);
            this._adapter.toggleHostAttribute(CHIP_CONSTANTS.attributes.DOWNLOAD, !!this._download?.trim(), this._download);
        }
    }
    get rel() {
        return this._rel;
    }
    set rel(value) {
        if (this._rel !== value) {
            this._rel = value;
            this._adapter.setAnchorProperty('rel', value);
            this._adapter.toggleHostAttribute(CHIP_CONSTANTS.attributes.REL, !!this._rel?.trim(), this._rel);
        }
    }
}
