import Event from '../../event/Event.js';
import * as PropertySymbol from '../../PropertySymbol.js';
import EventPhaseEnum from '../../event/EventPhaseEnum.js';
import ValidityState from '../../validity-state/ValidityState.js';
import HTMLElement from '../html-element/HTMLElement.js';
import HTMLLabelElementUtility from '../html-label-element/HTMLLabelElementUtility.js';
import { URL } from 'url';
import MouseEvent from '../../event/events/MouseEvent.js';
const BUTTON_TYPES = ['submit', 'reset', 'button', 'menu'];
/**
 * HTML Button Element.
 *
 * Reference:
 * https://developer.mozilla.org/en-US/docs/Web/API/HTMLButtonElement.
 */
export default class HTMLButtonElement extends HTMLElement {
    [PropertySymbol.validationMessage] = '';
    [PropertySymbol.validity] = new ValidityState(this);
    [PropertySymbol.formNode] = null;
    [PropertySymbol.popoverTargetElement] = null;
    /**
     * Returns validation message.
     *
     * @returns Validation message.
     */
    get validationMessage() {
        return this[PropertySymbol.validationMessage];
    }
    /**
     * Returns validity.
     *
     * @returns Validity.
     */
    get validity() {
        return this[PropertySymbol.validity];
    }
    /**
     * Returns name.
     *
     * @returns Name.
     */
    get name() {
        return this.getAttribute('name') || '';
    }
    /**
     * Sets name.
     *
     * @param name Name.
     */
    set name(name) {
        this.setAttribute('name', name);
    }
    /**
     * Returns value.
     *
     * @returns Value.
     */
    get value() {
        return this.getAttribute('value');
    }
    /**
     * Sets value.
     *
     * @param value Value.
     */
    set value(value) {
        this.setAttribute('value', value);
    }
    /**
     * Returns disabled.
     *
     * @returns Disabled.
     */
    get disabled() {
        return this.getAttribute('disabled') !== null;
    }
    /**
     * Sets disabled.
     *
     * @param disabled Disabled.
     */
    set disabled(disabled) {
        if (!disabled) {
            this.removeAttribute('disabled');
        }
        else {
            this.setAttribute('disabled', '');
        }
    }
    /**
     * Returns type
     *
     * @returns Type
     */
    get type() {
        const type = this.getAttribute('type');
        if (type === null || !BUTTON_TYPES.includes(type)) {
            return 'submit';
        }
        return type;
    }
    /**
     * Sets type
     *
     * @param value Type
     */
    set type(value) {
        this.setAttribute('type', value);
    }
    /**
     * Returns form action.
     *
     * @returns Form action.
     */
    get formAction() {
        if (!this.hasAttribute('formaction')) {
            return this[PropertySymbol.ownerDocument].location.href;
        }
        try {
            return new URL(this.getAttribute('formaction'), this[PropertySymbol.ownerDocument].location.href).href;
        }
        catch (e) {
            return '';
        }
    }
    /**
     * Sets form action.
     *
     * @param formAction Form action.
     */
    set formAction(formAction) {
        this.setAttribute('formaction', formAction);
    }
    /**
     * Returns form enctype.
     *
     * @returns Form enctype.
     */
    get formEnctype() {
        return this.getAttribute('formenctype') || '';
    }
    /**
     * Sets form enctype.
     *
     * @param formEnctype Form enctype.
     */
    set formEnctype(formEnctype) {
        this.setAttribute('formenctype', formEnctype);
    }
    /**
     * Returns form method.
     *
     * @returns Form method.
     */
    get formMethod() {
        return this.getAttribute('formmethod') || '';
    }
    /**
     * Sets form method.
     *
     * @param formMethod Form method.
     */
    set formMethod(formMethod) {
        this.setAttribute('formmethod', formMethod);
    }
    /**
     * Returns no validate.
     *
     * @returns No validate.
     */
    get formNoValidate() {
        return this.getAttribute('formnovalidate') !== null;
    }
    /**
     * Sets no validate.
     *
     * @param formNoValidate No validate.
     */
    set formNoValidate(formNoValidate) {
        if (!formNoValidate) {
            this.removeAttribute('formnovalidate');
        }
        else {
            this.setAttribute('formnovalidate', '');
        }
    }
    /**
     * Returns form target.
     *
     * @returns Form target.
     */
    get formTarget() {
        return this.getAttribute('formtarget') || '';
    }
    /**
     * Sets form target.
     *
     * @param formTarget Form target.
     */
    set formTarget(formTarget) {
        this.setAttribute('formtarget', formTarget);
    }
    /**
     * Returns the parent form element.
     *
     * @returns Form.
     */
    get form() {
        if (this[PropertySymbol.formNode]) {
            return this[PropertySymbol.formNode];
        }
        const id = this[PropertySymbol.attributes][PropertySymbol.namedItems].get('form')?.[PropertySymbol.value];
        if (!id || !this[PropertySymbol.isConnected]) {
            return null;
        }
        return this[PropertySymbol.ownerDocument].getElementById(id);
    }
    /**
     * Returns the associated label elements.
     *
     * @returns Label elements.
     */
    get labels() {
        return HTMLLabelElementUtility.getAssociatedLabelElements(this);
    }
    /**
     * Returns popover target element.
     *
     * @returns Popover target element.
     */
    get popoverTargetElement() {
        return this[PropertySymbol.popoverTargetElement];
    }
    /**
     * Sets popover target element.
     *
     * @param popoverTargetElement Popover target element.
     */
    set popoverTargetElement(popoverTargetElement) {
        if (popoverTargetElement !== null && !(popoverTargetElement instanceof HTMLElement)) {
            throw new this[PropertySymbol.window].TypeError(`Failed to set the 'popoverTargetElement' property on 'HTMLInputElement': Failed to convert value to 'Element'.`);
        }
        this[PropertySymbol.popoverTargetElement] = popoverTargetElement;
    }
    /**
     * Returns popover target action.
     *
     * @returns Popover target action.
     */
    get popoverTargetAction() {
        const value = this.getAttribute('popovertargetaction');
        if (value === null || (value !== 'hide' && value !== 'show' && value !== 'toggle')) {
            return 'toggle';
        }
        return value;
    }
    /**
     * Sets popover target action.
     *
     * @param value Popover target action.
     */
    set popoverTargetAction(value) {
        this.setAttribute('popovertargetaction', value);
    }
    /**
     * Checks validity.
     *
     * @returns "true" if the field is valid.
     */
    checkValidity() {
        const valid = this.disabled ||
            this.type === 'reset' ||
            this.type === 'button' ||
            this[PropertySymbol.validity].valid;
        if (!valid) {
            this.dispatchEvent(new Event('invalid', { bubbles: true, cancelable: true }));
        }
        return valid;
    }
    /**
     * Reports validity.
     *
     * @returns Validity.
     */
    reportValidity() {
        return this.checkValidity();
    }
    /**
     * Sets validation message.
     *
     * @param message Message.
     */
    setCustomValidity(message) {
        this[PropertySymbol.validationMessage] = String(message);
    }
    /**
     * @override
     */
    dispatchEvent(event) {
        if (event.type === 'click' &&
            event instanceof MouseEvent &&
            event.eventPhase === EventPhaseEnum.none &&
            this.disabled) {
            return false;
        }
        const returnValue = super.dispatchEvent(event);
        if (!event[PropertySymbol.defaultPrevented] &&
            event.type === 'click' &&
            event.eventPhase === EventPhaseEnum.none &&
            event instanceof MouseEvent) {
            const type = this.type;
            if (type === 'submit' || type === 'reset') {
                const form = this.form;
                if (form) {
                    if (type === 'submit' && this[PropertySymbol.isConnected]) {
                        form.requestSubmit(this);
                    }
                    else if (type === 'reset') {
                        form.reset();
                    }
                }
            }
        }
        return returnValue;
    }
}
//# sourceMappingURL=HTMLButtonElement.js.map