import { DomNodeSubject } from './dom-node-subject';
import { isParent } from '../../../../utils/ui';
/** The `DomNodesSubjectFactory` class is responsible for managing and caching `DomNodeSubject` objects associated with HTML elements. */
class DomNodeSubjectFactory {
  constructor() {
    this.cache = new Map();
  }
  /**
   * The function `getSubject` returns the subject associated with a given node and event ID, either from the cache or by setting it if it doesn't exist.
   *
   * @param {HTMLElement} node - The `node` parameter is an HTMLElement, which represents an element in the HTML document.
   * @param {VegaEventIDInterface} eventId - The `eventId` parameter is of type `VegaEventIDInterface`. It represents the ID of the event for which we want to get the subject.
   * @returns {DomNodeSubject} a `DomNodeSubject` object.
   */
  getSubject(node, eventId) {
    if (this.isExist(node, eventId)) {
      return this.cache.get(node).get(eventId);
    }
    else {
      return this.setSubject(node, eventId);
    }
  }
  /**
   * The function checks if a given node exists in the cache and if it has a specific event ID.
   *
   * @param {HTMLElement} node - The "node" parameter is an HTMLElement, which represents an HTML element in the DOM (Document Object Model). It could be any HTML element such as a div, span, button, etc.
   * @param {VegaEventIDInterface} eventId - The `eventId` parameter is of type `VegaEventIDInterface`. It represents an event ID that is used to identify a specific event.
   * @returns {boolean} a boolean value.
   */
  isExist(node, eventId) {
    if (node) {
      return (this.cache.has(node) &&
        this.cache.get(node) !== undefined &&
        this.cache.get(node).has(eventId));
    }
    return false;
  }
  /**
   * The function find if the parent of a given node exists in the cache and if it has a specific event ID.
   *
   * @param {HTMLElement} childNode - Child node.
   * @param {VegaEventIDInterface} eventId - eventId.
   * @returns {Nullable<DomNodeSubject>} - Parent node subject.
   */
  getSubjectFromParentNodeByEventId(childNode, eventId) {
    let subject;
    for (const entry of this.cache) {
      if (isParent(childNode, entry[0]) && entry[1].has(eventId)) {
        subject = entry[1].get(eventId);
        break;
      }
    }
    return subject;
  }
  /**
   * The function `setSubject` creates a new `DomNodeSubject` and associates it with a given `node` and `eventId`, and then returns the created subject.
   *
   * @param {HTMLElement} node - The `node` parameter is an HTMLElement object representing an HTML element in the DOM (Document Object Model).
   * @param {VegaEventIDInterface} eventId - The `eventId` parameter is of type `VegaEventIDInterface`. It represents the ID of a Vega event.
   * @returns {DomNodeSubject} dom node subject object
   */
  setSubject(node, eventId) {
    const subjectTitle = `${node.tagName}:${eventId.getName()}`;
    const subject = new DomNodeSubject(subjectTitle, node);
    if (!this.cache.get(node)) {
      this.cache.set(node, new Map());
    }
    this.cache.get(node).set(eventId, subject);
    return subject;
  }
}
export default new DomNodeSubjectFactory();
