import type { LocalChange } from 'injector/types';
import { applyHtmlChange } from './apply-html-change';
import { getElementFromChange } from './get-element-from-change';
export { getElementFromChange } from './get-element-from-change';
export * from './apply-globals';

export const applyChanges = (changes: LocalChange[], body = document.body) => {
  const unfoundChanges: LocalChange[] = [];

  for (let item of changes) {
    try {
      if (item.selectors?.length) {
        const multipleChanges: LocalChange[] = [];
        const selectors = item.selectors ?? [];
        const friendlySelectors = item.friendlySelectors ?? [];
        const friendlySelectorIndexes = item.friendlySelectorIndexes ?? [];
        for (let i = 0; i < selectors.length; i++) {
          const singleChange = {
            ...item,
            selectors: [],
            friendlySelectors: [],
            friendlySelectorIndexes: [],
            selector: selectors[i],
            friendlySelector: friendlySelectors[i],
            friendlySelectorIndex: friendlySelectorIndexes[i],
          } as LocalChange;
          multipleChanges.push(singleChange);
        }
        applyChanges(multipleChanges, body);
        continue;
      }
      if (item.selector) {
        const element: HTMLElement = getElementFromChange(item, body) as HTMLElement;

        if (!element) {
          unfoundChanges.push(item);
          continue;
        }

        item.element = element;
        item.clone = item.clone || (element.cloneNode(true) as HTMLElement);

        if (item.property === 'html') {
          applyHtmlChange(element, item);
          continue;
        }

        if (item.property === 'src' && item.value) {
          (element as HTMLImageElement).src = item.value || '';
          continue;
        }

        if (['textContent', 'text'].includes(item.property as string)) {
          element.textContent = item.value || '';
          continue;
        }

        if (item.property === 'backgroundImage') {
          element.style.backgroundImage = item.value ? `url(${item.value})` : '';
          continue;
        }

        if (item.property === 'dragPosition' && item.value) {
          const parsed = JSON.parse(item.value);
          if ('positionType' in parsed) {
            element.style.position = parsed.positionType;
            element.style.left = `${parsed.left}px`;
            element.style.top = `${parsed.top}px`;
          } else {
            element.style.position = parsed.position;
            element.style.left = parsed.left;
            element.style.top = parsed.top;
          }
          continue;
        }

        if (item.property === 'domMove' && item.value) {
          const { newParentSelector, newNextSiblingSelector } = JSON.parse(item.value);
          const newParent = newParentSelector ? body.querySelector(newParentSelector) : null;
          const newNextSibling = newNextSiblingSelector ? body.querySelector(newNextSiblingSelector) : null;
          if (newParent) {
            if (newNextSibling) {
              newParent.insertBefore(element, newNextSibling);
            } else {
              newParent.appendChild(element);
            }
          }
          continue;
        }

        if (typeof item.property === 'string') {
          element.style[item.property as any] = item.value || '';
        }
      }
    } catch (ex) {
      return [];
    }
  }
  return unfoundChanges;
};
