import { c as MapToComponentField, V as VegaSlimmer, I as InjectVegaSlimmer } from './global-slimmer-registry-17c4efd4.js';
import { c as createDynamicSlimmer } from './dynamic-slimmer-90b8af32.js';
import { C as ChangeManager } from './change-manager-6a7eb88c.js';
import { d as domNodeSubjectFactory, D as DomNodeSubjectObserverFactory } from './dom-node-subject-observer-factory-aca0116e.js';
import { j as jqueryDelegatedStrategyController, i as internalVegaEventManager } from './internal-vega-event-manager-7cdf3c28.js';
import { t as tryGetDocument } from './try-get-document-bef0f526.js';

var __decorate$3 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
  return c > 3 && r && Object.defineProperty(target, key, r), r;
};
/** The `VegaEventEmitHandlerSlimmer` class is a TypeScript class that handles the emission of Vega events based on the availability of the 'emit' function and the event semantics namespace. */
class VegaEventEmitHandlerSlimmer extends VegaSlimmer {
  constructor() {
    super(...arguments);
    /**
     * The function determines whether a Vega event should be emitted based on the namespace and the availability of the 'emit' function.
     *
     * @param {EventSemantics} namespace the event semantics namespace
     * @returns {boolean} a boolean value.
     */
    this.canHandle = ({ namespace }) => {
      return namespace === 'vega' || !this.nativeEvent || typeof this.nativeEvent['emit'] !== 'function';
    };
    /**
     * The function emits a Vega event with a given detail.
     *
     * @param {unknown} detail - The "detail" parameter is a generic type parameter that represents the data or
     * information that you want to emit with the event. It can be any type of data, such as a string,
     * number, object, or custom class.
     * @returns {CustomEvent} The emitted event.
     */
    this.handle = (detail) => {
      return this.vegaEvent.emit(detail);
    };
  }
}
__decorate$3([
  MapToComponentField()
], VegaEventEmitHandlerSlimmer.prototype, "vegaEvent", void 0);
__decorate$3([
  MapToComponentField()
], VegaEventEmitHandlerSlimmer.prototype, "nativeEvent", void 0);

var __decorate$2 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
  return c > 3 && r && Object.defineProperty(target, key, r), r;
};
/** The `NativeEventEmitHandlerSlimmer` class is a TypeScript class that handles emitting native events based on event semantics. */
class NativeEventEmitHandlerSlimmer extends VegaSlimmer {
  constructor() {
    super(...arguments);
    /**
     * The function determines whether a native event should be emitted based on the namespace of the event semantics.
     *
     * @param {EventSemantics} namespace the event semantics namespace
     * @returns {boolean} a boolean value.
     */
    this.canHandle = ({ namespace }) => {
      return namespace === 'native';
    };
    /**
     * The function emits a native event with a given detail.
     *
     * @param {unknown} detail - The `detail` parameter is a generic type `T` that represents the data or
     * information that you want to pass along with the event. It can be any type of data, such as a
     * string, number, object, or custom type.
     * @param {Event} [e] the event object
     * @returns {CustomEvent} The emitted event.
     */
    this.handle = (detail, e) => {
      if (e) {
        e.stopPropagation();
      }
      return this.nativeEvent.emit(detail);
    };
  }
}
__decorate$2([
  MapToComponentField()
], NativeEventEmitHandlerSlimmer.prototype, "nativeEvent", void 0);

var __decorate$1 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
  return c > 3 && r && Object.defineProperty(target, key, r), r;
};
/** The `JqueryDelegatedEventEmitHandlerSlimmer` class is a TypeScript class that handles emitting delegated events using jQuery. */
class JqueryDelegatedEventEmitHandlerSlimmer extends VegaSlimmer {
  constructor() {
    super(...arguments);
    /**
     * The function determines whether a jQuery delegated event should be emitted based on certain conditions.
     *
     * @param {EventSemantics} namespace the event semantics namespace
     * @returns {boolean} The function shouldEmitJqueryDelegatedEvent() returns a boolean value.
     */
    this.canHandle = ({ namespace, jqueryDelegatedEvent }) => {
      return (namespace === 'native' &&
        !!jqueryDelegatedEvent &&
        jqueryDelegatedStrategyController.isSupportDelegated(this.host, this.eventID));
    };
    /**
     * The function emits a delegated event with a given detail using a jQuery delegated event slimmer.
     *
     * @param {unknown} detail - The `detail` parameter is a generic type `T` that represents additional
     * information or data associated with the event. It can be any type of data that you want to pass
     * along with the event when it is emitted.
     * @param {Event} [e] the event object
     * @returns {Nullable<Event>} The emitted event.
     */
    this.handle = (detail, e) => {
      const strategy = jqueryDelegatedStrategyController.getStrategy(this.host, this.eventID);
      if (strategy) {
        if (e) {
          e.stopPropagation();
        }
        return strategy.handle(this.host, detail);
      }
    };
  }
  /**
   * The function "setEventID" sets the eventID property of the current object to the provided VegaEventID value.
   *
   * @param {VegaEventID} eventID - The eventID parameter is of type VegaEventID.
   */
  setEventID(eventID) {
    this.eventID = eventID;
  }
}
__decorate$1([
  MapToComponentField()
], JqueryDelegatedEventEmitHandlerSlimmer.prototype, "host", void 0);

var __decorate = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
  return c > 3 && r && Object.defineProperty(target, key, r), r;
};
/** The EventEmitSlimmerBase class is a TypeScript class that extends VegaSlimmer and provides methods for emitting events with or without notifications. */
class EventEmitSlimmerBase extends VegaSlimmer {
  /**
   * The constructor function takes an object with an eventName property and assigns it to the eventName property of the class.
   *
   * @param {{ eventName: string }} eventName  - The constructor function takes in an object with a property called "eventName" of type
   * string. The value of "eventName" is then assigned to the instance variable "this.eventName".
   */
  constructor({ eventID }) {
    super();
    this.vegaEventEmitHandler = new VegaEventEmitHandlerSlimmer();
    this.nativeEventEmitHandler = new NativeEventEmitHandlerSlimmer();
    this.jqueryDelegatedEventEmitHandler = new JqueryDelegatedEventEmitHandlerSlimmer();
    /**
     * emit the vega component event
     *
     * @param {unknown} [detail] the event detail
     * @param {Event} [e] the event object
     * @returns {Nullable<Event>} The emitted event.
     */
    this.emit = (detail, e) => {
      let isChangeManagerPrevented = false;
      ChangeManager.notify(domNodeSubjectFactory.getSubject(this.host, this.eventID), {
        host: this.host,
        detail: detail,
        eventName: this.eventName,
        // eslint-disable-next-line jsdoc/require-jsdoc
        preventDefault: () => {
          isChangeManagerPrevented = true;
        },
      });
      const eventSemantics = internalVegaEventManager.getSemantics(this.host);
      let event;
      for (const handler of this.eventHandlers) {
        if (handler.canHandle(eventSemantics)) {
          event = handler.handle(detail, e);
          break;
        }
      }
      if (event && isChangeManagerPrevented) {
        event.preventDefault();
      }
      return event;
    };
    /**
     * used to clean up and remove any observers that were added to the host element during the lifecycle of the class
     */
    this.removeObserverFromHost = () => {
      // add promise to fix the testPolyfill#replaceChildren
      void Promise.resolve(true).then(() => {
        if (this.isNodeRemovedFromDocument(this.host)) {
          DomNodeSubjectObserverFactory.removeUniqueObserverFromNode(this.host, this.eventID);
        }
      });
    };
    this.eventID = eventID;
    this.eventName = eventID.getVegaName();
    this.initialEventHandlers();
  }
  /**
   * The function checks if a given HTML element has been removed from the document.
   *
   * @param {Nullable<HTMLElement>} node - The `node` parameter is of type `Nullable<HTMLElement>`, which means it can either be
   * an `HTMLElement` or `null`. It represents the element that needs to be checked if it has been removed from the document.
   * @returns {boolean} a boolean value.
   */
  isNodeRemovedFromDocument(node) {
    var _a;
    // elementAppender#show will call the HTMLElement#append method, and the append method will call the component disconnectedCallback, but the component not remove from the page.
    // see the issue in test case vega-popover.e2e.ts->should behavior normal while click app header button and time picker nested in popover
    if (node && !((_a = tryGetDocument()) === null || _a === void 0 ? void 0 : _a.body.contains(node)) && !node.parentNode) {
      return true;
    }
    return false;
  }
  /**
   * The function initializes event handlers for different types of events.
   */
  initialEventHandlers() {
    this.jqueryDelegatedEventEmitHandler.setEventID(this.eventID);
    this.eventHandlers = [
      this.vegaEventEmitHandler,
      this.jqueryDelegatedEventEmitHandler,
      this.nativeEventEmitHandler,
    ];
  }
}
__decorate([
  InjectVegaSlimmer()
], EventEmitSlimmerBase.prototype, "vegaEventEmitHandler", void 0);
__decorate([
  InjectVegaSlimmer()
], EventEmitSlimmerBase.prototype, "nativeEventEmitHandler", void 0);
__decorate([
  InjectVegaSlimmer()
], EventEmitSlimmerBase.prototype, "jqueryDelegatedEventEmitHandler", void 0);
/**
 * The function `createEventEmitSlimmer` creates a slimmer version of an event emitter class by mapping specific properties and events.
 *
 * @param {ClassPrototype<unknown>} mapFromClass - The class prototype from which the event emitter will be created.
 * @param {VegaEventID} eventID - The eventName parameter is a VegaEventID that represents the name of the event.
 * @param {string} [nativeEventPropertyName] - usually the native event name is eventID#nativeName, set a property name when the native name is used by other method or property
 * @returns {EventEmitSlimmerBase} an instance of the `EventEmitSlimmerBase` class.
 */
function createEventEmitSlimmer(mapFromClass, eventID, nativeEventPropertyName) {
  const eventName = eventID.getVegaName();
  const nativeEventName = nativeEventPropertyName || eventID.getNativeName();
  return createDynamicSlimmer(mapFromClass, EventEmitSlimmerBase, [
    { mapFrom: 'host', mapTo: 'host' },
    { mapFrom: eventName, mapTo: 'vegaEvent' },
    //optional for now
    { mapFrom: nativeEventName, mapTo: 'nativeEvent', isOptional: true },
  ], [{ mapFrom: 'disconnectedCallback', mapTo: 'removeObserverFromHost' }], [
    {
      eventID,
    },
  ]);
}

export { createEventEmitSlimmer as c };
