const compareTokens = (original: string, comparison: string) => {
  const originalTokens = new Set(original.split(' '));
  const comparisonTokens = new Set(comparison.split(' '));
  return [...originalTokens].filter(token => !comparisonTokens.has(token));
};

export class MutationHelper {
  static fireClassChange(
    record: MutationRecord,
    node: HTMLElement | null,
    fn: (classes: DOMTokenList) => void,
  ) {
    if (node && record.oldValue !== node?.classList.value) {
      fn(node?.classList);
    }
  }

  static fireClassAdded(
    record: MutationRecord,
    node: HTMLElement | null,
    classMap: Map<string, () => void>,
  ) {
    if (node && record.oldValue) {
      const tokens = compareTokens(node?.classList.value, record.oldValue);
      tokens.forEach(className => classMap.get(className)?.());
    }
  }

  static fireClassRemoved(
    record: MutationRecord,
    node: HTMLElement | null,
    classMap: Map<string, () => void>,
  ) {
    if (node && record.oldValue) {
      const tokens = compareTokens(record.oldValue, node?.classList.value);
      tokens.forEach(className => classMap.get(className)?.());
    }
  }

  static fireSubtreeChange(nodes: NodeList, fn?: (nodes: NodeList) => void) {
    if (nodes.length && fn) {
      fn(nodes);
    }
  }

  static isClass(mutation: MutationRecord) {
    return mutation.type === 'attributes' && mutation.attributeName === 'class';
  }

  static isChildList(mutation: MutationRecord) {
    return mutation.type === 'childList';
  }
}
