/**
 * @license
 * Copyright 2023 Tyler Technologies, Inc. 
 * License: Apache-2.0
 */
import { FIELD_CONSTANTS } from './field-constants';
export class FieldFoundation {
    constructor(_adapter) {
        this._adapter = _adapter;
        this._density = 'default';
        this._shape = 'default';
        this._invalid = false;
        this._required = false;
        this._floatLabelType = 'auto';
        this._isInitialized = false;
        this._labelSlotListener = evt => this._onLabelSlotChanged(evt);
        this._leadingSlotListener = evt => this._onLeadingSlotChanged(evt);
        this._trailingSlotListener = evt => this._onTrailingSlotChanged(evt);
        this._addonEndSlotListener = evt => this._onAddonEndSlotChanged(evt);
        this._focusListener = (evt) => this._onFocus(evt);
        this._blurListener = (evt) => this._onBlur(evt);
        this._valueChangedListener = (value) => this._onValueChanged(value);
        this._inputAttributeChangedListener = (name, value) => this._onInputAttributeChanged(name, value);
    }
    //
    // Public
    //
    initialize() {
        this._adapter.initialize('');
        if (this._adapter.hasLabel()) {
            this._adapter.ensureSlottedLabel();
        }
        this._initializeLabel();
        if (this._adapter.hasPlaceholder()) {
            this._floatLabelType = 'always';
        }
        this._detectSlottedContent();
        this._adapter.addLabelSlotListener(this._labelSlotListener);
        this._adapter.addLeadingSlotListener(this._leadingSlotListener);
        this._adapter.addTrailingSlotListener(this._trailingSlotListener);
        this._adapter.addAddonEndSlotListener(this._addonEndSlotListener);
        this._adapter.setValueChangedListener(this, this._valueChangedListener);
        this._adapter.addInputListener('focus', this._focusListener);
        this._adapter.addInputListener('blur', this._blurListener);
        this._adapter.setInputAttributeObserver(this._inputAttributeChangedListener);
        this._applyDensity();
        this._setShapeType();
        this._setValidity();
        if (this._adapter.isDisabled()) {
            this._adapter.setRootClass(FIELD_CONSTANTS.classes.DISABLED);
        }
        else {
            this._adapter.removeRootClass(FIELD_CONSTANTS.classes.DISABLED);
        }
        if (this._adapter.isReadonly()) {
            this._adapter.setRootClass(FIELD_CONSTANTS.classes.READONLY);
        }
        else {
            this._adapter.removeRootClass(FIELD_CONSTANTS.classes.READONLY);
        }
        if (this._floatLabelType === 'always') {
            this.floatLabel(true);
        }
        this._isInitialized = true;
    }
    disconnect() {
        this._isInitialized = false;
        this._adapter.destroy();
        this._adapter.removeHostAttribute(FIELD_CONSTANTS.attributes.HOST_LABEL_FLOATING);
        this._adapter.removeRootClass(FIELD_CONSTANTS.classes.LABEL);
        if (this._floatingLabel) {
            this._floatingLabel.destroy();
            this._floatingLabel = undefined;
        }
        this._adapter.removeLabelSlotListener(this._labelSlotListener);
        this._adapter.removeLeadingSlotListener(this._leadingSlotListener);
        this._adapter.removeTrailingSlotListener(this._trailingSlotListener);
        this._adapter.removeAddonEndSlotListener(this._addonEndSlotListener);
        this._adapter.removeInputListener('focus', this._focusListener);
        this._adapter.removeInputListener('blur', this._blurListener);
        this._adapter.destroyValueChangeListener();
    }
    get density() {
        return this._density;
    }
    set density(value) {
        if (this._density !== value) {
            const prevDensity = this._density;
            this._density = value;
            if (this._isInitialized) {
                this._applyDensity();
                if (this._density === 'dense') {
                    this._destroyFloatingLabel({ cancelFloat: true });
                }
                else if (prevDensity === 'dense') {
                    this._initializeLabel();
                }
            }
            this._adapter.setHostAttribute(FIELD_CONSTANTS.attributes.DENSITY, this._density.toString());
        }
    }
    get floatLabelType() {
        return this._floatLabelType;
    }
    set floatLabelType(value) {
        if (this._floatLabelType !== value) {
            this._floatLabelType = value;
            if (this._isInitialized) {
                this.floatLabel(this._floatLabelType === 'always');
            }
            this._adapter.setHostAttribute(FIELD_CONSTANTS.attributes.FLOAT_LABEL_TYPE, this._floatLabelType);
        }
    }
    get shape() {
        return this._shape;
    }
    set shape(value) {
        if (this._shape !== value) {
            this._shape = value;
            if (this._isInitialized) {
                this._setShapeType();
            }
            this._adapter.setHostAttribute(FIELD_CONSTANTS.attributes.SHAPE, this._shape);
        }
    }
    get invalid() {
        return this._invalid;
    }
    set invalid(value) {
        if (this._invalid !== value) {
            this._invalid = value;
            if (this._isInitialized) {
                this._setValidity();
            }
        }
    }
    get required() {
        return this._required;
    }
    set required(value) {
        if (this._required !== value) {
            this._required = value;
            if (this._isInitialized) {
                this._setValidity();
            }
            if (this._required) {
                this._adapter.setHostAttribute(FIELD_CONSTANTS.attributes.REQUIRED);
            }
            else {
                this._adapter.removeHostAttribute(FIELD_CONSTANTS.attributes.REQUIRED);
            }
        }
    }
    floatLabel(value) {
        var _a, _b;
        if (((_a = this._floatingLabel) === null || _a === void 0 ? void 0 : _a.isFloating) === value || this._adapter.isLabelFloating() === value) {
            if (value) {
                this._adapter.setHostAttribute(FIELD_CONSTANTS.attributes.HOST_LABEL_FLOATING, '');
            }
            return;
        }
        if (!value && this._floatLabelType === 'always') {
            (_b = this._floatingLabel) === null || _b === void 0 ? void 0 : _b.float(true, true);
            this._adapter.setHostAttribute(FIELD_CONSTANTS.attributes.HOST_LABEL_FLOATING, '');
            return;
        }
        if (this._floatingLabel) {
            this._floatingLabel.float(value, this._floatLabelType === 'always');
            if (value) {
                this._adapter.setInputClass(FIELD_CONSTANTS.classes.INPUT_FOCUSED);
                this._adapter.setHostAttribute(FIELD_CONSTANTS.attributes.HOST_LABEL_FLOATING, '');
            }
            else {
                this._adapter.removeInputClass(FIELD_CONSTANTS.classes.INPUT_FOCUSED);
                this._adapter.removeHostAttribute(FIELD_CONSTANTS.attributes.HOST_LABEL_FLOATING);
            }
        }
    }
    //
    // Protected
    //
    _onLabelSlotChanged(evt) {
        this._initializeLabel();
    }
    _onLeadingSlotChanged(evt) {
        this._detectLeadingContent();
    }
    _onTrailingSlotChanged(evt) {
        this._detectTrailingContent();
    }
    _onAddonEndSlotChanged(evt) {
        this._detectAddonEndContent();
    }
    _initializeLabel() {
        var _a;
        (_a = this._floatingLabel) === null || _a === void 0 ? void 0 : _a.destroy();
        this._adapter.detectLabel();
        if (this._adapter.hasLabel() && this._density !== 'dense') {
            this._floatingLabel = this._adapter.initializeFloatingLabel();
            this.floatLabel(this._floatLabelType === 'always' || this._adapter.fieldHasValue() || this._adapter.hasPlaceholder());
            this._adapter.setRootClass(FIELD_CONSTANTS.classes.LABEL);
        }
        else {
            this._destroyFloatingLabel();
        }
    }
    _destroyFloatingLabel({ cancelFloat = false } = {}) {
        var _a;
        this._adapter.removeHostAttribute(FIELD_CONSTANTS.attributes.HOST_LABEL_FLOATING);
        this._adapter.removeRootClass(FIELD_CONSTANTS.classes.LABEL);
        (_a = this._floatingLabel) === null || _a === void 0 ? void 0 : _a.destroy({ cancelFloat });
        this._floatingLabel = undefined;
    }
    _detectLeadingContent() {
        if (this._adapter.hasLeadingNodes()) {
            this._adapter.setRootClass(FIELD_CONSTANTS.classes.LEADING);
        }
        else {
            this._adapter.removeRootClass(FIELD_CONSTANTS.classes.LEADING);
        }
    }
    _detectTrailingContent() {
        if (this._adapter.hasTrailingNodes()) {
            this._adapter.setRootClass(FIELD_CONSTANTS.classes.TRAILING);
        }
        else {
            this._adapter.removeRootClass(FIELD_CONSTANTS.classes.TRAILING);
        }
    }
    _detectAddonEndContent() {
        if (this._adapter.hasAddonEndNodes()) {
            this._adapter.setRootClass(FIELD_CONSTANTS.classes.ADDON_END);
        }
        else {
            this._adapter.removeRootClass(FIELD_CONSTANTS.classes.ADDON_END);
        }
    }
    _detectSlottedContent() {
        this._detectLeadingContent();
        this._detectTrailingContent();
        this._detectAddonEndContent();
    }
    _onFocus(evt) {
        this._adapter.setRootClass(FIELD_CONSTANTS.classes.FOCUSED);
        this._adapter.setLabelClass(FIELD_CONSTANTS.classes.LABEL_FOCUSED);
        this.floatLabel(true);
    }
    _onBlur(evt) {
        if (this._adapter.inputHasFocus(evt.relatedTarget)) {
            return;
        }
        this._adapter.removeRootClass(FIELD_CONSTANTS.classes.FOCUSED);
        this._adapter.removeLabelClass(FIELD_CONSTANTS.classes.LABEL_FOCUSED);
        if (!this._adapter.fieldHasValue() && !this._adapter.hasPlaceholder()) {
            this.floatLabel(false);
            this._adapter.removeHostAttribute(FIELD_CONSTANTS.attributes.HOST_LABEL_FLOATING);
        }
    }
    _onValueChanged(value) {
        if (this._adapter.fieldHasValue()) {
            this.floatLabel(true);
        }
        else if (!this._adapter.inputHasFocus() && !this._adapter.hasPlaceholder()) {
            this.floatLabel(false);
        }
    }
    _onInputAttributeChanged(name, value) {
        if (this._adapter.isDisabled()) {
            this._adapter.setRootClass(FIELD_CONSTANTS.classes.DISABLED);
            this._adapter.removeRootClass(FIELD_CONSTANTS.classes.FOCUSED);
            this._adapter.removeInputClass(FIELD_CONSTANTS.classes.INPUT_FOCUSED);
            this._adapter.removeLabelClass(FIELD_CONSTANTS.classes.LABEL_FOCUSED);
            if (!this._adapter.fieldHasValue() && !this._adapter.hasPlaceholder() && this._floatingLabel) {
                this.floatLabel(false);
            }
        }
        else {
            this._adapter.removeRootClass(FIELD_CONSTANTS.classes.DISABLED);
        }
        if (this._adapter.isReadonly()) {
            this._adapter.setRootClass(FIELD_CONSTANTS.classes.READONLY);
        }
        else {
            this._adapter.removeRootClass(FIELD_CONSTANTS.classes.READONLY);
            this._adapter.removeRootClass(FIELD_CONSTANTS.classes.FOCUSED);
            this._adapter.removeInputClass(FIELD_CONSTANTS.classes.INPUT_FOCUSED);
        }
        switch (name) {
            case 'readonly':
            case 'disabled':
                // If we are changing the readonly or disabled attribute, we want to make sure that we apply
                // the focus state properly if the input element also now has focus
                if (this._adapter.inputHasFocus()) {
                    this._adapter.setRootClass(FIELD_CONSTANTS.classes.FOCUSED);
                    this._adapter.setInputClass(FIELD_CONSTANTS.classes.INPUT_FOCUSED);
                    this._adapter.setLabelClass(FIELD_CONSTANTS.classes.LABEL_FOCUSED);
                }
                break;
            case 'value':
                if (this._floatingLabel) {
                    this.floatLabel(this._adapter.fieldHasValue());
                }
                break;
            case 'placeholder':
                if (this._floatingLabel) {
                    const float = (!!value && !!value.trim()) || this._adapter.fieldHasValue();
                    if (float !== this._floatingLabel.isFloating) {
                        this.floatLabel(float);
                    }
                }
                break;
        }
    }
    _setShapeType() {
        if (this._shape === 'rounded') {
            this._adapter.setRootClass(FIELD_CONSTANTS.classes.SHAPE_ROUNDED);
        }
        else {
            this._adapter.removeRootClass(FIELD_CONSTANTS.classes.SHAPE_ROUNDED);
        }
    }
    _setValidity() {
        if (this._invalid) {
            this._adapter.setRootClass(FIELD_CONSTANTS.classes.INVALID);
        }
        else {
            this._adapter.removeRootClass(FIELD_CONSTANTS.classes.INVALID);
        }
        if (this._required) {
            this._adapter.setRootClass(FIELD_CONSTANTS.classes.REQUIRED);
        }
        else {
            this._adapter.removeRootClass(FIELD_CONSTANTS.classes.REQUIRED);
        }
    }
    _applyDensity() {
        this._adapter.setRoomy(this._density === 'roomy');
        this._adapter.setDense(this._density === 'dense');
    }
}
