/**
 * @license
 * Copyright Tyler Technologies, Inc. 
 * License: Apache-2.0
 */
import { task } from '../core/utils/event-utils';
import { LABEL_CONSTANTS } from './label-constants';
export class LabelFoundation {
    constructor(_adapter) {
        this._adapter = _adapter;
        this._dynamic = false;
        this._nonInteractive = false;
        this._legend = false;
        this._isConnected = false;
        this._clickListener = (evt) => this._handleClick(evt);
        this._slotChangeListener = () => this._handleSlotChange();
        this._mutationCallback = () => this._handleMutation();
    }
    initialize() {
        if (this._legend) {
            this._initializeAsLegend();
        }
        else {
            this._initializeAsLabel();
        }
    }
    disconnect() {
        this._disconnect();
        this._adapter.destroy();
    }
    update() {
        this._adapter.updateTargetLabel();
    }
    /**
     * Emit an event to give ancestor elements a chance to connect
     */
    async _initializeAsLegend() {
        // Give ancestor elements a chance to connect to the DOM
        // TODO: see if this works in Angular
        await task();
        this._adapter.emitHostEvent(LABEL_CONSTANTS.events.CONNECTED);
    }
    /**
     * Search for child or id-targetted elements to connect to
     */
    async _initializeAsLabel() {
        var _a;
        this._adapter.addSlotChangeListener(this._slotChangeListener);
        this._adapter.trySetTarget((_a = this._for) !== null && _a !== void 0 ? _a : null);
        if (this._adapter.hasTargetElement()) {
            this._connect();
        }
    }
    _handleClick(evt) {
        var _a;
        // Prevent duplicate clicks from a nested target element or if the event originates
        // from within the target element
        const targetEl = (_a = this._clickTarget) !== null && _a !== void 0 ? _a : this._adapter.getTargetElement();
        if (evt.target === targetEl || (targetEl === null || targetEl === void 0 ? void 0 : targetEl.contains(evt.target))) {
            return;
        }
        this._adapter.clickTarget();
    }
    _handleSlotChange() {
        if (!this._for && !this._forElement) {
            this._adapter.trySetTarget(null);
            this._tryConnect();
        }
    }
    _handleMutation() {
        this._adapter.updateTargetLabel();
    }
    _connect() {
        if (!this._nonInteractive) {
            this._adapter.addHostListener('click', this._clickListener);
        }
        this._adapter.updateTargetLabel();
        if (this._dynamic) {
            this._adapter.addMutationObserver(this._mutationCallback);
        }
        this._isConnected = true;
    }
    _disconnect() {
        this._adapter.removeHostListener('click', this._clickListener);
        this._adapter.removeMutationObserver();
        this._isConnected = false;
    }
    _tryConnect() {
        if (!this._adapter.hasTargetElement()) {
            this._disconnect();
        }
        else if (!this._isConnected) {
            this._connect();
        }
    }
    get for() {
        return this._for;
    }
    set for(value) {
        var _a, _b;
        if (this._for !== value) {
            this._for = value;
            this._adapter.toggleHostAttribute(LABEL_CONSTANTS.attributes.FOR, !!this.for, (_a = this.for) !== null && _a !== void 0 ? _a : undefined);
            this._adapter.trySetTarget((_b = this._for) !== null && _b !== void 0 ? _b : null);
            this._tryConnect();
        }
    }
    get forElement() {
        return this._forElement;
    }
    set forElement(value) {
        var _a;
        if (this._forElement !== value) {
            this._forElement = value;
            this._adapter.setTargetElement((_a = this._forElement) !== null && _a !== void 0 ? _a : null);
            this._tryConnect();
        }
    }
    get clickTarget() {
        return this._clickTarget;
    }
    set clickTarget(value) {
        if (this._clickTarget !== value) {
            this._clickTarget = value;
        }
    }
    get dynamic() {
        return this._dynamic;
    }
    set dynamic(value) {
        if (this._dynamic !== value) {
            this._dynamic = value;
            this._adapter.toggleHostAttribute(LABEL_CONSTANTS.attributes.DYNAMIC, this._dynamic);
            if (!this._dynamic) {
                this._adapter.removeMutationObserver();
            }
            else if (this._adapter.hasTargetElement()) {
                this._adapter.addMutationObserver(this._mutationCallback);
            }
        }
    }
    get nonInteractive() {
        return this._nonInteractive;
    }
    set nonInteractive(value) {
        if (this._nonInteractive !== value) {
            this._nonInteractive = value;
            this._adapter.toggleHostAttribute(LABEL_CONSTANTS.attributes.NON_INTERACTIVE, this._nonInteractive);
            // The click listener is only added if the label is connected
            if (!this._isConnected) {
                return;
            }
            if (this._nonInteractive) {
                this._adapter.removeHostListener('click', this._clickListener);
            }
            else {
                this._adapter.addHostListener('click', this._clickListener);
            }
        }
    }
    get legend() {
        return this._legend;
    }
    set legend(value) {
        var _a;
        if (this._legend !== value) {
            this._legend = value;
            this._adapter.toggleHostAttribute(LABEL_CONSTANTS.attributes.LEGEND, this._legend);
            if (this._legend) {
                this._adapter.removerSlotChangeListener(this._slotChangeListener);
                this._adapter.emitHostEvent(LABEL_CONSTANTS.events.CONNECTED);
                return;
            }
            this._adapter.addSlotChangeListener(this._slotChangeListener);
            this._adapter.trySetTarget((_a = this._for) !== null && _a !== void 0 ? _a : null);
            if (this._adapter.hasTargetElement()) {
                this._connect();
            }
        }
    }
}
