/**
 * @license
 * Copyright Tyler Technologies, Inc. 
 * License: Apache-2.0
 */
import { task } from '../../core/utils/event-utils';
import { RADIO_CONSTANTS } from './radio-constants';
export class RadioFoundation {
    constructor(_adapter) {
        this._adapter = _adapter;
        // State
        this._checked = false;
        this._defaultChecked = false;
        this._value = 'on';
        this._disabled = false;
        this._required = false;
        this._readonly = false;
        this._dense = false;
        this._labelPosition = 'end';
        this._focusListener = () => this._handleFocus();
        this._blurListener = () => this._handleBlur();
        this._clickListener = (evt) => this._handleClick(evt);
        this._keydownListener = (evt) => this._handleKeydown(evt);
        this._keyupListener = (evt) => this._handleKeyup(evt);
    }
    initialize() {
        this._adapter.addHostListener('focus', this._focusListener);
        this._adapter.addHostListener('blur', this._blurListener);
        this._adapter.addHostListener('click', this._clickListener, { capture: true });
        this._adapter.addHostListener('keydown', this._keydownListener);
        this._adapter.addHostListener('keyup', this._keyupListener, { capture: true });
        this._adapter.setChecked(this._checked, this._value);
    }
    // Public methods
    tryCheck() {
        this._checked = true;
        if (!this._dispatchEvents()) {
            this._checked = false;
            return false;
        }
        this._adapter.setChecked(this._checked, this._value);
        this._adapter.toggleHostAttribute(RADIO_CONSTANTS.attributes.CHECKED, this._checked);
        return true;
    }
    // Event handlers
    _handleFocus() {
        if (!this._checked) {
            this._adapter.setUncheckedRadioGroupFocus('focus');
        }
    }
    _handleBlur() {
        if (!this._checked) {
            this._adapter.setUncheckedRadioGroupFocus('blur');
        }
    }
    _handleClick(evt) {
        this._activate(evt);
    }
    _handleKeydown(evt) {
        switch (evt.key) {
            case 'ArrowRight':
            case 'ArrowDown':
                evt.preventDefault();
                this._adapter.focusNext();
                break;
            case 'ArrowLeft':
            case 'ArrowUp':
                evt.preventDefault();
                this._adapter.focusPrevious();
                break;
            case ' ':
                // Prevent the spacebar from scrolling the page
                evt.preventDefault();
                break;
        }
    }
    _handleKeyup(evt) {
        if (evt.key === ' ') {
            this._activate(evt);
        }
    }
    /**
     * Checks the radio button if it is not disabled or readonly. Exits early if the activating
     * event is cancelled.
     */
    async _activate(evt) {
        if (this._checked || this._disabled || this._readonly) {
            return;
        }
        // Wait a task to allow the event to propagate to user code.
        await task();
        if (evt.defaultPrevented) {
            return;
        }
        this._checked = true;
        if (!this._dispatchEvents()) {
            this._checked = false;
            return;
        }
        this._adapter.setChecked(this._checked, this._value);
        this._adapter.toggleHostAttribute(RADIO_CONSTANTS.attributes.CHECKED, this._checked);
    }
    /**
     * Dispatches change and input events.
     *
     * @returns {boolean} - Returns true if neither event was cancelled.
     */
    _dispatchEvents() {
        // Emit both change and input events per the spec.
        const changeEvent = new Event(RADIO_CONSTANTS.events.CHANGE, { bubbles: true, cancelable: true });
        const inputEvent = new Event(RADIO_CONSTANTS.events.INPUT, { bubbles: true, cancelable: true, composed: true });
        this._adapter.dispatchHostEvent(changeEvent);
        this._adapter.dispatchHostEvent(inputEvent);
        return !(changeEvent.defaultPrevented || inputEvent.defaultPrevented);
    }
    get checked() {
        return this._checked;
    }
    set checked(value) {
        if (this._checked !== value) {
            this._checked = value;
            this._adapter.setChecked(this._checked, this._value);
            this._adapter.toggleHostAttribute(RADIO_CONSTANTS.attributes.CHECKED, this._checked);
        }
    }
    get defaultChecked() {
        return this._defaultChecked;
    }
    set defaultChecked(value) {
        if (this._defaultChecked !== value) {
            this._defaultChecked = value;
            this._adapter.toggleHostAttribute(RADIO_CONSTANTS.attributes.DEFAULT_CHECKED, this._defaultChecked);
        }
    }
    get value() {
        return this._value;
    }
    set value(value) {
        if (this._value !== value) {
            this._value = value;
            this._adapter.setHostAttribute(RADIO_CONSTANTS.attributes.VALUE, this._value);
        }
    }
    get disabled() {
        return this._disabled;
    }
    set disabled(value) {
        if (this._disabled !== value) {
            this._disabled = value;
            // Attempt to set disabled, restore if unsuccessful
            if (this._adapter.trySetDisabled(this._disabled)) {
                this._adapter.disableStateLayer(this._disabled || this._readonly);
                this._adapter.toggleHostAttribute(RADIO_CONSTANTS.attributes.DISABLED, this._disabled);
            }
            else {
                this._disabled = !this._disabled;
            }
        }
    }
    get required() {
        return this._required;
    }
    set required(value) {
        if (this._required !== value) {
            this._required = value;
            this._adapter.setRequired(this._required);
            this._adapter.toggleHostAttribute(RADIO_CONSTANTS.attributes.REQUIRED, this._required);
        }
    }
    get readonly() {
        return this._readonly;
    }
    set readonly(value) {
        if (this._readonly !== value) {
            this._readonly = value;
            this._adapter.setReadonly(this._readonly);
            this._adapter.disableStateLayer(this._disabled || this._readonly);
            this._adapter.toggleHostAttribute(RADIO_CONSTANTS.attributes.READONLY, this._readonly);
        }
    }
    get dense() {
        return this._dense;
    }
    set dense(value) {
        if (this._dense !== value) {
            this._dense = value;
            this._adapter.toggleHostAttribute(RADIO_CONSTANTS.attributes.DENSE, this._dense);
        }
    }
    get labelPosition() {
        return this._labelPosition;
    }
    set labelPosition(value) {
        if (this._labelPosition !== value) {
            this._labelPosition = value;
            this._adapter.setLabelPosition(this._labelPosition);
            this._adapter.setHostAttribute(RADIO_CONSTANTS.attributes.LABEL_POSITION, this._labelPosition);
        }
    }
}
