'use strict';

const vegaEventId = require('./vega-event-id-f95480b7.js');
const globalSlimmerRegistry = require('./global-slimmer-registry-b3bce7e0.js');

const entries = [
  ['vega-accordion', [vegaEventId.VegaExpand]],
  ['vega-app-header-button', [vegaEventId.VegaClick, vegaEventId.VegaDropdownClick, vegaEventId.VegaReset, vegaEventId.VegaDropdownSearch]],
  ['vega-banner', [vegaEventId.VegaClose, vegaEventId.VegaActionButtonClick]],
  ['vega-breadcrumb', [vegaEventId.VegaClick]],
  ['vega-button', [vegaEventId.VegaClick]],
  ['vega-button-circle', [vegaEventId.VegaClick]],
  ['vega-button-group', [vegaEventId.VegaClick]],
  ['vega-button-link', [vegaEventId.VegaClick]],
  [
    'vega-calendar',
    [vegaEventId.VegaChange, vegaEventId.VegaEventClick, vegaEventId.VegaDateDblClick, vegaEventId.VegaMoreActionClick, vegaEventId.VegaDateClick, vegaEventId.VegaEventEdit],
  ],
  ['vega-carousel', [vegaEventId.VegaPageUpdate]],
  ['vega-checkbox', [vegaEventId.VegaChange]],
  ['vega-checkbox-group', [vegaEventId.VegaChange]],
  ['vega-chip', [vegaEventId.VegaClose, vegaEventId.VegaClick]],
  ['vega-code-block', [vegaEventId.VegaChange, vegaEventId.VegaRemove]],
  ['vega-color-picker', [vegaEventId.VegaChange]],
  ['vega-color-swatch', [vegaEventId.VegaClick]],
  ['vega-color-swatch-picker', [vegaEventId.VegaChange]],
  ['vega-combo-box', [vegaEventId.VegaChange, vegaEventId.VegaCreate, vegaEventId.VegaSearch]],
  ['vega-date-picker', [vegaEventId.VegaChange, vegaEventId.VegaMonthYearChange]],
  ['vega-date-picker-calendar', [vegaEventId.VegaClear, vegaEventId.VegaMonthYearChange, vegaEventId.VegaSelectionChange]],
  [
    'vega-dropdown',
    [
      vegaEventId.VegaDropdownShow,
      vegaEventId.VegaDropdownHide,
      vegaEventId.VegaDropdownClick,
      vegaEventId.VegaReset,
      vegaEventId.VegaCreate,
      vegaEventId.VegaDropdownSearch,
      vegaEventId.VegaSearchTrigger,
    ],
  ],
  ['vega-dropdown-item', [vegaEventId.VegaClick]],
  ['vega-field-label', [vegaEventId.VegaClick, vegaEventId.VegaLabelButtonClick]],
  ['vega-file-uploader', [vegaEventId.VegaChange, vegaEventId.VegaSelectFileChange, vegaEventId.VegaRemove, vegaEventId.VegaRetry, vegaEventId.VegaPreview]],
  ['vega-form', [vegaEventId.VegaFormSubmit, vegaEventId.VegaFormReset, vegaEventId.VegaValidate]],
  ['vega-image-uploader', [vegaEventId.VegaChange, vegaEventId.VegaRemove, vegaEventId.VegaCancel]],
  [
    'vega-input',
    [
      vegaEventId.VegaChange,
      vegaEventId.VegaNativeInputChange,
      vegaEventId.VegaFocus,
      vegaEventId.VegaBlur,
      vegaEventId.VegaLabelButtonClick,
      vegaEventId.VegaSuggestionItemClick,
      vegaEventId.VegaPaste,
    ],
  ],
  ['vega-input-credit-card', [vegaEventId.VegaChange, vegaEventId.VegaBlur, vegaEventId.VegaFocus]],
  ['vega-input-numeric', [vegaEventId.VegaChange]],
  ['vega-input-passcode', [vegaEventId.VegaChange, vegaEventId.VegaComplete]],
  ['vega-input-phone-number', [vegaEventId.VegaChange, vegaEventId.VegaCountryChange]],
  ['vega-input-range', [vegaEventId.VegaChange]],
  [
    'vega-input-select',
    [vegaEventId.VegaChange, vegaEventId.VegaSearch, vegaEventId.VegaSearchTrigger, vegaEventId.VegaShow, vegaEventId.VegaHide, vegaEventId.VegaLabelButtonClick],
  ],
  ['vega-item-toggle', [vegaEventId.VegaToggleStatus]],
  ['vega-modal', [vegaEventId.VegaOpen, vegaEventId.VegaClose]],
  ['vega-left-nav', [vegaEventId.VegaStateUpdate]],
  ['vega-left-nav-group', [vegaEventId.VegaGroupClick]],
  ['vega-left-nav-link', [vegaEventId.VegaMenuClick]],
  ['vega-left-nav-section', [vegaEventId.VegaActionClick]],
  ['vega-pagination', [vegaEventId.VegaChange, vegaEventId.VegaPageSizeChange]],
  ['vega-popover', [vegaEventId.VegaPopoverShow, vegaEventId.VegaPopoverHide]],
  ['vega-progress-tracker', [vegaEventId.VegaCurrentStepUpdate]],
  ['vega-radio', [vegaEventId.VegaChange, vegaEventId.VegaFocus, vegaEventId.VegaBlur]],
  ['vega-radio-group', [vegaEventId.VegaChange]],
  ['vega-rich-text-editor', [vegaEventId.VegaChange, vegaEventId.VegaImageInserted, vegaEventId.VegaSourceCodeChange]],
  ['vega-rich-text-editor-toolbar-button', [vegaEventId.VegaClick]],
  ['vega-rich-text-image-editor', [vegaEventId.VegaChange]],
  ['vega-rich-text-link-editor', [vegaEventId.VegaChange]],
  ['vega-segment-control', [vegaEventId.VegaChange]],
  ['vega-selection-chip', [vegaEventId.VegaChange]],
  ['vega-selection-chip-group', [vegaEventId.VegaChange]],
  ['vega-selection-tile', [vegaEventId.VegaChange]],
  ['vega-selection-tile-group', [vegaEventId.VegaChange]],
  ['vega-sidenav', [vegaEventId.VegaStateUpdate]],
  ['vega-sidenav-link', [vegaEventId.VegaClick]],
  ['vega-signature-capture', [vegaEventId.VegaChange]],
  ['vega-stepper', [vegaEventId.VegaChange]],
  ['vega-tab-group', [vegaEventId.VegaClick]],
  [
    'vega-table',
    [
      vegaEventId.VegaChange,
      vegaEventId.VegaSelectChange,
      vegaEventId.VegaSelectAllChange,
      vegaEventId.VegaRowClick,
      vegaEventId.VegaRowExpand,
      vegaEventId.VegaRowDragDrop,
      vegaEventId.VegaRowSelect,
      vegaEventId.VegaRowSelectAll,
    ],
  ],
  ['vega-table-head-cell', [vegaEventId.VegaClick]],
  ['vega-table-row', [vegaEventId.VegaClick, vegaEventId.VegaExpand]],
  ['vega-textarea', [vegaEventId.VegaChange, vegaEventId.VegaBlur, vegaEventId.VegaLabelButtonClick]],
  ['vega-time-picker', [vegaEventId.VegaChange]],
  ['vega-toggle-switch', [vegaEventId.VegaChange]],
];
const VEGA_COMPONENT_EVENT_MAP = new Map(entries);

/** The code is defining an abstract class called `BaseStrategy` that implements the `JQueryDelegatedEventStrategy` interface. */
class BaseStrategy {
  /**
   * The function "getHostName" returns the VegaComponentName.
   *
   * @returns {VegaComponentName} The method is returning the value of the variable "vegaComponentName" of type VegaComponentName.
   */
  getHostName() {
    return this.vegaComponentName;
  }
  /**
   * The function "getEventName" returns the name of an event as a string.
   *
   * @returns {VegaNativeEventNameType} a string value, which is the eventName.
   */
  getEventName() {
    return this.eventName;
  }
  /**
   * The function handles a click event on a specified element and dispatches a custom event with an optional detail.
   *
   * @param {HTMLElement} vegaHost - The `vegaHost` parameter is an HTMLElement that represents the host element where the event will be dispatched.
   * @param {unknown} [detail] - The `detail` parameter is an optional argument that represents additional information or data that can be passed along with the event. It can be of any type, as it is defined as `unknown`.
   * @returns {Event} a custom event of type `Event`.
   */
  handle(vegaHost, detail) {
    const target = this.createEventTarget(vegaHost);
    target.style.display = 'none';
    vegaHost.appendChild(target);
    const clonedEvent = this.createEvent(this.eventName);
    if (detail) {
      Object.defineProperty(clonedEvent, 'detail', {
        configurable: true,
        value: detail,
      });
    }
    target.dispatchEvent(clonedEvent);
    target.remove();
    return clonedEvent;
  }
  /**
   * The function copies attributes from one HTML element to another, excluding attributes starting with "on", "id".
   *
   * @param {HTMLElement} element - The `element` parameter is an HTMLElement object that represents the
   * source element from which the attributes will be copied.
   * @param {HTMLElement} target - The target parameter is an HTMLElement where the attributes of the
   * element parameter will be copied to.
   */
  copyAttributesToTarget(element, target) {
    if (element && target) {
      const attributes = Array.from(element.attributes).filter((attr) => !attr.name.startsWith('on'));
      attributes.forEach((attr) => {
        try {
          target.setAttribute(attr.name, attr.value);
        }
        catch (_a) {
          globalSlimmerRegistry.LogUtility.error(`Delegated strategy copy ${element.tagName} attribute '${attr.name}' error.`);
        }
      });
    }
  }
  /**
   * The function creates and returns a new event object based on the given event name.
   *
   * @param {VegaNativeEventNameType} eventName - The eventName parameter is the name of the event that
   * you want to create. It can be any valid event name, such as "click", "keydown", "mouseover", etc.
   * @returns {Event} a cloned event object.
   */
  createEvent(eventName) {
    let clonedEvent = new Event(eventName, { bubbles: true, cancelable: true });
    if (eventName === 'click') {
      clonedEvent = new MouseEvent(eventName, { bubbles: true, cancelable: true });
    }
    return clonedEvent;
  }
}

/** The VegaButtonClickStrategy class is responsible for creating a button element when a click event is triggered on a VegaButton component. */
class VegaButtonClickStrategy extends BaseStrategy {
  constructor() {
    super(...arguments);
    this.eventName = 'click';
    this.vegaComponentName = 'vega-button';
  }
  /**
   * The function creates a new HTML button element based on the properties of a delegated target.
   *
   * @param {HTMLElement} delegatedTarget - The delegatedTarget parameter is of type
   * HTMLVegaButtonElement, which is a custom element that extends the HTMLButtonElement. It represents
   * the target button element that will be delegated to create a new button element.
   * @returns {HTMLButtonElement} an HTMLButtonElement.
   */
  createEventTarget(delegatedTarget) {
    // eslint-disable-next-line no-restricted-globals
    const button = document.createElement('button');
    this.copyAttributesToTarget(delegatedTarget, button);
    button.type = delegatedTarget.type;
    return button;
  }
}

/** The VegaCheckboxChangeStrategy class is responsible for creating an event target and handling the change event for Vega checkboxes. */
class VegaCheckboxChangeStrategy extends BaseStrategy {
  constructor() {
    super(...arguments);
    this.eventName = 'change';
    this.vegaComponentName = 'vega-checkbox';
  }
  /**
   * The function creates and returns a checkbox input element with the same name as the given delegated target.
   *
   * @param {HTMLElement} delegatedTarget - The delegatedTarget parameter is of type
   * HTMLVegaCheckboxElement, which is a custom element representing a checkbox component in the Vega UI framework.
   * @returns {HTMLInputElement} an HTMLInputElement.
   */
  createEventTarget(delegatedTarget) {
    // eslint-disable-next-line no-restricted-globals
    const input = document.createElement('input');
    this.copyAttributesToTarget(delegatedTarget, input);
    input.type = 'checkbox';
    input.checked = delegatedTarget.checked;
    return input;
  }
}

/** The VegaInputSelectChangeStrategy class is a TypeScript class that extends the BaseStrategy class and is used for handling the 'change' event for Vega input select components. */
class VegaInputSelectChangeStrategy extends BaseStrategy {
  constructor() {
    super(...arguments);
    this.eventName = 'change';
    this.vegaComponentName = 'vega-input-select';
  }
  /**
   * The function creates a new HTML select element and sets its name attribute based on the name attribute of the delegated target.
   *
   * @param {HTMLElement} delegatedTarget - The delegatedTarget parameter is of type
   * HTMLVegaInputSelectElement, which is a custom element that represents an input select element in the Vega framework.
   * @returns {HTMLSelectElement} an HTMLSelectElement.
   */
  createEventTarget(delegatedTarget) {
    // eslint-disable-next-line no-restricted-globals
    const select = document.createElement('select');
    this.copyAttributesToTarget(delegatedTarget, select);
    if (delegatedTarget.value) {
      select.value = delegatedTarget.value.toString();
    }
    return select;
  }
}

/** The VegaInputBlurStrategy class is responsible for creating an input element when a blur event is triggered on a VegaInput component. */
class VegaInputStrategy extends BaseStrategy {
  /**
   * The constructor function initializes an instance of a class with a given eventName.
   *
   * @param {VegaNativeEventNameType} eventName - The eventName parameter is a string that represents the name of the event.
   */
  constructor(eventName) {
    super();
    this.vegaComponentName = 'vega-input';
    this.eventName = eventName;
  }
  /**
   * The function creates a new HTML input element with the same type as the provided delegated target.
   *
   * @param {HTMLElement} delegatedTarget - The delegatedTarget parameter is an
   * HTMLVegaInputElement, which is a custom type or interface that represents an input element in the
   * Vega framework. It likely has properties and methods specific to the Vega framework that are not
   * present in the standard HTMLInputElement.
   * @returns {HTMLInputElement} an HTMLInputElement.
   */
  createEventTarget(delegatedTarget) {
    // eslint-disable-next-line no-restricted-globals
    const input = document.createElement('input');
    this.copyAttributesToTarget(delegatedTarget, input);
    input.type = delegatedTarget.type;
    input.value = delegatedTarget.value;
    return input;
  }
}

/** The VegaRadioChangeStrategy class is responsible for creating an input element for radio buttons and handling the 'change' event. */
class VegaRadioChangeStrategy extends BaseStrategy {
  constructor() {
    super(...arguments);
    this.eventName = 'change';
    this.vegaComponentName = 'vega-radio';
  }
  /**
   * The function creates and returns a radio input element with the same name as the given delegated target.
   *
   * @param {HTMLElement} delegatedTarget - The delegatedTarget parameter is an
   * HTMLVegaRadioElement, which is a custom element that represents a radio button in the Vega UI framework.
   * @returns {HTMLInputElement} an HTMLInputElement.
   */
  createEventTarget(delegatedTarget) {
    // eslint-disable-next-line no-restricted-globals
    const input = document.createElement('input');
    this.copyAttributesToTarget(delegatedTarget, input);
    input.type = 'radio';
    input.checked = delegatedTarget.checked;
    return input;
  }
}

/** The VegaTextareaChangeStrategy class is a TypeScript class that extends the BaseStrategy class and is used for handling the 'change' event for a VegaTextarea component. */
class VegaTextareaChangeStrategy extends BaseStrategy {
  constructor() {
    super(...arguments);
    this.vegaComponentName = 'vega-textarea';
    this.eventName = 'change';
  }
  /**
   * The function creates a textarea element and sets its name attribute based on the name attribute of a delegated target element.
   *
   * @param {HTMLElement} delegatedTarget - The delegatedTarget parameter is an HTMLVegaTextElement, which is an element that represents a text input field in the Vega visualization library.
   * @returns {HTMLTextAreaElement} an HTMLTextAreaElement.
   */
  createEventTarget(delegatedTarget) {
    // eslint-disable-next-line no-restricted-globals
    const textarea = document.createElement('textarea');
    this.copyAttributesToTarget(delegatedTarget, textarea);
    textarea.value = delegatedTarget.value;
    return textarea;
  }
}

/** The `JQueryDelegatedStrategyController` class manages delegated event strategies for different HTML elements in a TypeScript application. */
class JQueryDelegatedStrategyController {
  /**
   * The constructor initializes a registry of update strategies for various input events in a Vega application.
   */
  constructor() {
    this.strategyRegistry = new Map();
    this.updateStrategyRegistry([
      new VegaButtonClickStrategy(),
      new VegaInputStrategy('change'),
      new VegaInputStrategy('focus'),
      new VegaInputStrategy('blur'),
      new VegaInputSelectChangeStrategy(),
      new VegaTextareaChangeStrategy(),
      new VegaCheckboxChangeStrategy(),
      new VegaRadioChangeStrategy(),
    ]);
  }
  /**
   * The function checks if a given event on a specific HTML element is supported for delegation.
   *
   * @param {HTMLElement} host - The `host` parameter is an HTMLElement, which represents the element on which the event listener is attached.
   * @param {VegaEventID} eventId - The `eventName` parameter is a string that represents the name of the event.
   * @returns {boolean} a boolean value.
   */
  isSupportDelegated(host, eventId) {
    let result = false;
    const componentName = host.tagName.toLowerCase();
    if (!!this.strategyRegistry.get(componentName) &&
      !!this.strategyRegistry.get(componentName).get(eventId.getNativeName())) {
      result = true;
    }
    return result;
  }
  /**
   * The function updates the strategy registry with custom strategies based on the event semantics configuration.
   *
   * @param {EventSemanticsConfig} eventSemantics - The parameter `eventSemantics` is of type `EventSemanticsConfig`. It is an object that contains two properties: `global` and `components`.
   */
  updateRegistryFromEventSemantics(eventSemantics) {
    let customStrategies = [];
    const { global, components } = eventSemantics;
    if (global && Array.isArray(global.jqueryDelegatedEvent)) {
      customStrategies = customStrategies.concat(global.jqueryDelegatedEvent);
    }
    if (components) {
      for (const name in components) {
        if (Array.isArray(components[name].jqueryDelegatedEvent)) {
          customStrategies = customStrategies.concat(components[name].jqueryDelegatedEvent);
        }
      }
    }
    if (customStrategies.length) {
      this.updateStrategyRegistry(customStrategies);
    }
  }
  /**
   * The function returns a delegated event strategy based on the host element and event name.
   *
   * @param {HTMLElement} host - The `host` parameter is an HTMLElement that represents the element on
   * which the event strategy is being applied. It is the element to which the event listener is attached.
   * @param {VegaEventID} eventId - The `eventName` parameter is a string that represents the name of the event for which you want to retrieve the strategy.
   * @returns {Nullable<JQueryDelegatedEventStrategy>} a Nullable<JQueryDelegatedEventStrategy>.
   */
  getStrategy(host, eventId) {
    const componentName = host.tagName.toLowerCase();
    if (this.strategyRegistry && this.strategyRegistry.get(componentName)) {
      return this.strategyRegistry.get(componentName).get(eventId.getNativeName());
    }
  }
  /**
   * The function `overrideCurrentStrategy` updates the strategy registry with a new strategy for a specific host and event.
   *
   * @param {JQueryDelegatedEventStrategy[]} strategies - The parameter "strategy" is of type "JQueryDelegatedEventStrategy".
   */
  updateStrategyRegistry(strategies) {
    strategies.forEach((strategy) => {
      const hostName = strategy.getHostName();
      const eventName = strategy.getEventName();
      if (!this.strategyRegistry.get(hostName)) {
        const map = new Map();
        map.set(eventName, strategy);
        this.strategyRegistry.set(hostName, map);
      }
      else {
        this.strategyRegistry.get(hostName).set(eventName, strategy);
      }
    });
  }
}
const jqueryDelegatedStrategyController = new JQueryDelegatedStrategyController();

/**
 * The `InternalVegaEventManager` class manages event semantics configuration for global and
 * component-specific settings.
 */
class InternalVegaEventManager {
  constructor() {
    this.config = {};
    this.defaultEventSemantics = {
      namespace: 'vega',
    };
  }
  /**
   * The function sets the semantics configuration for events.
   *
   * @param {EventSemanticsConfig} config - The `config` parameter is of type `EventSemanticsConfig`.
   */
  setSemantics(config) {
    this.config = config;
    jqueryDelegatedStrategyController.updateRegistryFromEventSemantics(config);
  }
  /**
   * The function `getSemantics` returns the event semantics either from the global scope or from the
   * components within a given host element.
   *
   * @param {HTMLElement} host - The host parameter is an HTMLElement that represents the element on
   * which the event semantics are being checked.
   * @returns {EventSemantics} The method `getSemantics` returns a value of type `Nullable<EventSemantics>`.
   */
  getSemantics(host) {
    return Object.assign({}, this.defaultEventSemantics, this.getSemanticsInGlobal(), this.getSemanticsInComponents(host));
  }
  /**
   * The function "getEnabledEventIdsByComponent" returns an array of event Ids associated with a given component
   * name.
   *
   * @param {VegaComponentName} componentName - The `componentName` parameter is a string that represents
   * the name of a Vega component.
   * @returns {Nullable<VegaEventID[]>} a nullable array of VegaEventID objects.
   */
  getEnabledEventIdsByComponent(componentName) {
    return VEGA_COMPONENT_EVENT_MAP.get(componentName);
  }
  /**
   * The function `getSemanticsInGlobal` returns the global event semantics configuration.
   *
   * @returns {Nullable<EventSemantics>} The method is returning a nullable EventSemantics object.
   */
  getSemanticsInGlobal() {
    return this.config.global;
  }
  /**
   * The function `getSemanticsInComponents` returns the semantic configuration for a given component
   * based on its host element.
   *
   * @param {HTMLElement} host - The `host` parameter is an HTMLElement that represents the component for
   * which we want to retrieve the semantics.
   * @returns {Nullable<EventSemantics>} a value of type `Nullable<EventSemantics>`.
   */
  getSemanticsInComponents(host) {
    const componentName = host.tagName.toLocaleLowerCase();
    if (this.config.components &&
      Object.prototype.hasOwnProperty.call(this.config.components, componentName)) {
      return this.config.components[componentName];
    }
    return null;
  }
}
const internalVegaEventManager = new InternalVegaEventManager();

exports.BaseStrategy = BaseStrategy;
exports.internalVegaEventManager = internalVegaEventManager;
exports.jqueryDelegatedStrategyController = jqueryDelegatedStrategyController;
