import split from 'lodash.split';

import { cnAdd } from '@/internal/cn';
import { doc } from '@/internal/env';

import {
  ISplitTextLetterMeta,
  ISplitTextStaticProps,
  ISplitTextWordMeta,
} from '../types';

import { isIgnored } from './isIgnored';

interface IProps {
  wordsMeta: ISplitTextWordMeta[];
  classname: string;
  tagName: keyof HTMLElementTagNameMap;
  ignore: ISplitTextStaticProps['ignore'];
}

/**
 * Wraps each letter in every word inside the container with the specified HTML tag and class name.
 */
export function wrapLetters({ wordsMeta, classname, tagName, ignore }: IProps) {
  const lettersMeta: ISplitTextLetterMeta[] = [];

  const baseElement = doc.createElement(tagName);
  baseElement.style.display = 'inline-block';
  cnAdd(baseElement, classname);

  // Iterate over each word to wrap its letters
  wordsMeta.forEach((wordMeta) => {
    if (isIgnored(wordMeta.element, ignore)) {
      return;
    }

    const textNode = wordMeta.element.childNodes[0];
    if (!textNode) {
      return;
    }

    const text = textNode.textContent;

    if (!text) {
      return;
    }

    // Split the word into individual letters
    const splitLetters = split(text, '');

    splitLetters.forEach((letterContents) => {
      const element = baseElement.cloneNode(false) as HTMLElement;
      element.appendChild(doc.createTextNode(letterContents));

      // Append the letter element to the word's container
      wordMeta.element.insertBefore(element, textNode);

      const letter: ISplitTextLetterMeta = { element };

      // Add the letter to the word's letters array and the global letters array
      wordMeta.letters.push(letter);
      lettersMeta.push(letter);
    });

    // Remove the original text node after wrapping the letters
    textNode.remove();
  });

  return { lettersMeta };
}
