/**
 * @license
 * Copyright Tyler Technologies, Inc. 
 * License: Apache-2.0
 */
import { CHIP_FIELD_CONSTANTS } from './chip-field-constants';
import { BaseFieldCore } from '../field/base/base-field-core';
export class ChipFieldCore extends BaseFieldCore {
    constructor(adapter) {
        super(adapter);
        this._addOnBlur = false;
        this._mouseDownListener = this._onMouseDown.bind(this);
        this._clickListener = this._onClick.bind(this);
        this._rootKeyDownListener = this._onRootKeyDown.bind(this);
        this._inputKeyDownListener = this._onKeyDown.bind(this);
        this._slotChangeListener = this._onSlotChange.bind(this);
        this._inputAttributeListener = this._onInputAttributeChange.bind(this);
        this._valueChangeListener = this._onValueChange.bind(this);
        this._inputListener = this._onValueChange.bind(this);
        this._blurListener = this._onBlur.bind(this);
    }
    initialize() {
        this._adapter.initialize();
        this._adapter.addRootListener('mousedown', this._mouseDownListener, { capture: true });
        this._adapter.addRootListener('click', this._clickListener);
        this._adapter.addRootListener('keydown', this._rootKeyDownListener);
        this._adapter.addInputListener('keydown', this._inputKeyDownListener);
        this._adapter.addRootListener('slotchange', this._slotChangeListener);
        this._adapter.addRootListener('input', this._inputListener);
        this._adapter.tryAddValueChangeListener(this, this._valueChangeListener);
        if (this._addOnBlur) {
            this._adapter.addInputListener('blur', this._blurListener);
        }
    }
    destroy() {
        this._adapter.removeRootListener('mousedown', this._mouseDownListener, { capture: true });
        this._adapter.removeRootListener('click', this._clickListener);
        this._adapter.removeRootListener('keydown', this._rootKeyDownListener);
        this._adapter.removeInputListener('keydown', this._inputKeyDownListener);
        this._adapter.removeRootListener('slotchange', this._slotChangeListener);
        this._adapter.removeRootListener('input', this._inputListener);
        this._adapter.removeInputListener('blur', this._blurListener);
        this._adapter.removeValueChangeListener();
    }
    _onBlur(event) {
        const input = event.target;
        if (this._addOnBlur) {
            this._addMember(input);
        }
        input.value = '';
    }
    _onMouseDown(evt) {
        if (this._disabled || this._adapter.inputHasFocus) {
            evt.preventDefault();
            evt.stopPropagation();
            return;
        }
    }
    _onClick(_evt) {
        if (this._disabled) {
            return;
        }
        this._adapter.focusInput();
        this._adapter.clickInput();
    }
    _onValueChange() {
        this._tryFloatLabel();
    }
    _onSlotChange(evt) {
        const target = evt.target;
        switch (target.name) {
            case 'label':
                this._adapter.tryConnectSlottedLabel(target);
                break;
            case 'member':
                this._adapter.toggleContainerClass(CHIP_FIELD_CONSTANTS.classes.HAS_MEMBERS, target.assignedElements().length > 0);
                this._adapter.tryFloatLabel();
                this._adapter.getSlottedMemberElements().forEach(x => (x.tabIndex = -1));
                break;
            case '':
                this._adapter.handleDefaultSlotChange(target, this._inputAttributeListener);
                this._adapter.tryAddValueChangeListener(this, this._valueChangeListener);
                this._tryFloatLabel();
                break;
        }
    }
    _onInputAttributeChange(name, value) {
        switch (name) {
            case 'disabled':
                this.disabled = value !== null;
                break;
            case 'placeholder':
                this._tryFloatLabel();
                break;
        }
    }
    _onRootKeyDown({ key }) {
        if (this._adapter.hasInputValue) {
            return;
        }
        switch (key) {
            case 'ArrowRight':
                this._focusNextMember();
                break;
            case 'ArrowLeft':
                this._focusPreviousMember();
                break;
            case 'Backspace':
            case 'Delete':
                this._removeMember();
                break;
        }
    }
    _onKeyDown({ target, key }) {
        const input = target;
        switch (key) {
            case 'Enter':
                this._addMember(input);
                break;
            case 'Escape':
                input.value = '';
                break;
            case 'Tab':
                if (!this._addOnBlur) {
                    input.value = '';
                }
                break;
        }
    }
    _focusNextMember() {
        const members = this._adapter.getSlottedMemberElements();
        if (!members.length || this._adapter.inputHasFocus) {
            return;
        }
        for (let i = 0; i < members.length; i++) {
            const member = members.at(i);
            const nextMember = members.at(i + 1);
            if (member && this._isMemberActive(member)) {
                if (nextMember) {
                    nextMember.focus();
                    break;
                }
                else {
                    this._adapter.focusInput();
                }
            }
        }
    }
    _focusPreviousMember() {
        const members = this._adapter.getSlottedMemberElements();
        if (!members.length) {
            return;
        }
        if (this._adapter.inputHasFocus) {
            members[members.length - 1].focus();
            return;
        }
        for (let i = 0; i < members.length; i++) {
            const previousMember = members.at(i - 1);
            const member = members.at(i);
            if (member && this._isMemberActive(member) && previousMember) {
                previousMember.focus();
                break;
            }
        }
    }
    _isMemberActive(el) {
        return el.matches(':focus-within');
    }
    _getActiveMember() {
        const members = this._adapter.getSlottedMemberElements();
        return members.find(x => this._isMemberActive(x)) ?? null;
    }
    _addMember(input) {
        const cleanInputValue = input.value.trim();
        if (cleanInputValue.length > 0) {
            this._adapter.emitHostEvent(CHIP_FIELD_CONSTANTS.events.MEMBER_ADDED, cleanInputValue);
        }
        input.value = '';
    }
    _removeMember() {
        let memberToRemove = this._getActiveMember();
        if (!memberToRemove) {
            const members = this._adapter.getSlottedMemberElements();
            memberToRemove = members.at(-1);
        }
        if (!memberToRemove) {
            return;
        }
        this._focusNextMember();
        this._adapter.emitHostEvent(CHIP_FIELD_CONSTANTS.events.MEMBER_REMOVED, memberToRemove);
    }
    get addOnBlur() {
        return this._addOnBlur;
    }
    set addOnBlur(value) {
        value = Boolean(value);
        if (this._addOnBlur !== value) {
            this._addOnBlur = value;
            if (this._adapter.isConnected) {
                if (this._addOnBlur) {
                    this._adapter.addInputListener('blur', this._blurListener);
                }
                else {
                    this._adapter.removeInputListener('blur', this._blurListener);
                }
            }
            this._adapter.toggleHostAttribute(CHIP_FIELD_CONSTANTS.attributes.ADD_ON_BLUR, this._addOnBlur);
        }
    }
    get popoverTargetElement() {
        return this._adapter.popoverTargetElement;
    }
    get disabled() {
        return super.disabled;
    }
    set disabled(value) {
        if (this.disabled === value) {
            return;
        }
        super.disabled = value;
        this._adapter.setDisabled(value);
    }
}
